Aller au contenu

Photo

Secret Compartment Container (Solved and Improved)


  • Veuillez vous connecter pour répondre
22 réponses à ce sujet

#1
Alupinu

Alupinu
  • Members
  • 528 messages
I’m having a little trouble getting this script to work. Wondering if somebody could possible tell me the problem.
The script is for a secret compartment on a container. This is how it works, player opens container sees junk. If player chooses to leave junk in container nothing happens. If player removes junk from container then script fires. A new item appears in container and a speaker string informs player of secret compartment.
Now if I put the ResRef directly in the code the script fires fine. But if I try to do it using “string sTemplate” nothing happens. …why?
 
*SCRIPT START*
//Put this script On Inventory Disturbed Script
//Created by Alupinu
 
void main(string sTemplate)
{
 
object oPC = GetLastUsedBy();
 
//if (!GetIsPC(oPC)) return;
 
int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));
 
if (DoOnce==TRUE) return;
 
SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);
 
CreateItemOnObject(sTemplate, OBJECT_SELF);
 
ActionSpeakString("*SUCCESS* You found a secret compartment in the chest.");
 
}
 
*SCRIPT ENDS*
Thank you.

Modifié par Alupinu, 02 mai 2012 - 09:03 .


#2
rjshae

rjshae
  • Members
  • 4 491 messages
Why would any value get passed in through "string sTemplate"?

#3
bealzebub

bealzebub
  • Members
  • 352 messages
I believe you need to include;
#include "ginc_actions"
before void main.

#4
kamal_

kamal_
  • Members
  • 5 250 messages
Is sTemplate initialized? Perhaps as a local variable.

sTemplate = GetLocalString(OBJECT_SELF, "sItem");
CreateItemOnObject(sTemplate, OBJECT_SELF);

In fact, void main (string sTemplate) could be just void main()
{
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");
....
}

#5
Morbane

Morbane
  • Members
  • 1 883 messages
Alu:

You might find this script helpful - I just dug it up so how helpful it might be is debatable

// OnInventoryDisturbed
void main()
{
int iType = GetInventoryDisturbType();
object oSphere = GetInventoryDisturbItem();
object oPC = GetLastDisturbed();

switch(iType)
{
case INVENTORY_DISTURB_TYPE_ADDED:
{
// Set local int if PC adds the sphere to inventory
if(GetTag(oSphere) == "sphere_1")
SetLocalInt(oPC, "one", 1);
break;
}
case INVENTORY_DISTURB_TYPE_REMOVED:
{
// Delete the variable if the sphere is removed.
if(GetTag(oSphere) == "sphere_1")
DeleteLocalInt(oPC, "one");
break;
}
}
}



#6
bealzebub

bealzebub
  • Members
  • 352 messages
Kamal is right. give the chest a variable called sItem. and make the string, the Resref of the object you want created.


void main()
{

object oPC = GetLastUsedBy();
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");


int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));

if (DoOnce==TRUE) return;

SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);

CreateItemOnObject(sTemplate, OBJECT_SELF);

ActionSpeakString("*SUCCESS* You found a secret compartment in the chest.");

}

#7
Morbane

Morbane
  • Members
  • 1 883 messages
A mish-mash of all of the above :)

// OnInventoryDisturbed
void main()
{
int iType = GetInventoryDisturbType();
object oSphere = GetInventoryDisturbItem();
object oPC = GetLastDisturbed();
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");

if(GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF))) return;

switch(iType)
{
case INVENTORY_DISTURB_TYPE_REMOVED:
{
CreateItemOnObject(sTemplate, OBJECT_SELF);

SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);
break;
}
}
}



#8
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
If you write it the way you wrote it:

void main(string sTemplate)
{
code;
}

Then you need to call it from a conversation where you can fill in the value of sTemplate. Alternatively you could use the ExecuteScriptEnhanced() function in tandem with the function AddScriptParameterString() and call your script from another script, but that would be complicating things needlessly. 

If you are putting your script in the OnDisturbed event of the container, then you don't want to write the script this way.

I'd either define sTemplate using a local string on the container, like Kamal suggested, to give more versatility, or just defining it in the script if you only plan on using the script once or twice.

Modifié par M. Rieder, 01 mai 2012 - 04:25 .


#9
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages
I would use a tag-based on acquire script for the junk item, not a script on the container. When the item is acquired do whatever you want, once of course.

If you do use the on disturbed script on the container then on any remove event you need to check if the junk item is still in the container, because the person might have added another item to the container and then removed their item and not the junk item. Only if the junk item is no longer in the container should you do the rest. To make the script generically useful assign the tags of the junk item and good item in local string variables on the container and retrieve them with GetLocalString.

Regards

#10
kamal_

kamal_
  • Members
  • 5 250 messages
I handle hidden compartments with an ondisturbed script for the chest that runs a skill check the first time, and if passed spawns a second chest as the "hidden compartment", along with the message to the player. Might be easier. Let's me have more than one item hidden, and let's me separately lock/trap the hidden compartment.

#11
Alupinu

Alupinu
  • Members
  • 528 messages
Hey everybody! Thanks for your replies. I see what I was doing wrong now I was trying to make a conversation (ga_) script work as a placeable (gp_) or object script. As you all can see my scripting skills are not quite up to power with the rest of you people.Image IPB Kamal_ was right, I needed to give the chest a local variable. Once I did that the script started working fine, I even added a quantity variable so I wouldn’t need to make a separate blueprints. I thought about adding a search function but that starting to get to complicated and above my scripting skills. Besides not sure if its really that nesassery.

After reading everybody’s commendts this is what I came up with.
****
// OnInventoryDisturbed
void main()
{
 
int iType = GetInventoryDisturbType();
object oSphere = GetInventoryDisturbItem();
object oPC = GetLastUsedBy();
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");
int nQuantity = GetLocalInt(OBJECT_SELF, "nQuantity");
 
 
int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));
 
if (DoOnce==TRUE) return;
 
if(GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF))) return;
 
switch(iType)
{
case INVENTORY_DISTURB_TYPE_REMOVED:
{
 
SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);
 
CreateItemOnObject(sTemplate, OBJECT_SELF, nQuantity);
 
ActionSpeakString("*SUCCESS* You found a secret compartment in the chest.");
 
}
}

}
****
My biggest worry was having the CreatItem loop but that doesn’t seem to be a problem.
I think this will do it, thanks again everybody!

Modifié par Alupinu, 01 mai 2012 - 08:51 .


#12
Morbane

Morbane
  • Members
  • 1 883 messages
nevermind :innocent:

Modifié par Morbane, 01 mai 2012 - 09:04 .


#13
Morbane

Morbane
  • Members
  • 1 883 messages
// OnInventoryDisturbed
void main()
{

int iType = GetInventoryDisturbType();
//object oSphere = GetInventoryDisturbItem();
object oPC = GetLastUsedBy();
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");
int nQuantity = GetLocalInt(OBJECT_SELF, "nQuantity");

if(GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF)) == TRUE) return;

switch(iType)
{
case INVENTORY_DISTURB_TYPE_REMOVED:
{

SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);

CreateItemOnObject(sTemplate, OBJECT_SELF, nQuantity);

ActionSpeakString("*SUCCESS* You found a secret compartment in the chest.");

}
}

}

You had your "do once" stuff mixed up - the above shows all you need to have for that

Modifié par Morbane, 01 mai 2012 - 10:03 .


#14
Alupinu

Alupinu
  • Members
  • 528 messages
@Morbane, IC, your right I don’t need it. Not sure I understand why but thanks.

#15
Morbane

Morbane
  • Members
  • 1 883 messages
It is because the SetLocalInt() inside the DISTURBED case only triggers if someone actually takes the junk out - then they can only do it once.

Where you has the :

int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));

if (DoOnce==TRUE) return;

above the DISTURBED event it would kill the script even if they did not take the junk out.

#16
Alupinu

Alupinu
  • Members
  • 528 messages
IC... Thanks again Morbane.

#17
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages
This code will incorrectly trigger your success result even when someone puts some other item in the container and then removes it rather than removing your junk item. Since it should only be success when the junk item is removed I suggest you store the tag of the junk item as a local string variable on the container and then in the remove case verify that the junk item is no longer in the container before your success result.

Regards

#18
Morbane

Morbane
  • Members
  • 1 883 messages
I dont think it really matters because it will only trigger the secret compartment once - perhaps simply moving the junk around serves the same purpose :\\

#19
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages

Morbane wrote...

I dont think it really matters because it will only trigger the secret compartment once - perhaps simply moving the junk around serves the same purpose :


The stated requirement in the first post was that when the junk is removed the success logic should occur.  If that is truly a requirement then you need to check if the junk item was actually removed. Otherwise the implemented code doesn't match the stated requirement.  What do they call that when that happens... oh right, a bug.

Regards

#20
Alupinu

Alupinu
  • Members
  • 528 messages
@Kaldor, why don't you give us a copy of your version of the script with the conditional? It's not that I think it's a bad idea its just that I'm lazy, the script seems to work fine with out it. Now if I had a version with the conditional than I'm sure I would use it.

Also may I add what probable takes you 10 min to script is most likely a 2-3 hour trip to hell for me. Image IPB

Modifié par Alupinu, 02 mai 2012 - 08:53 .


#21
kevL

kevL
  • Members
  • 4 061 messages
lol, my latest trip to hell was yesterday, when I was cleaning out and backing up my campaign and module folders ( lost the association of module <-> campaign ), and then accidentally clicked X on the CampaignScripts tab .....

/ot

#22
Morbane

Morbane
  • Members
  • 1 883 messages
// OnInventoryDisturbed
void main()
{

int iType = GetInventoryDisturbType();
object oItem = GetInventoryDisturbItem();
object oPC = GetLastUsedBy();
string sTemplate = GetLocalString(OBJECT_SELF, "sItem");
int nQuantity = GetLocalInt(OBJECT_SELF, "nQuantity");

if(GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF)) == TRUE) return;

switch(iType)
{
case INVENTORY_DISTURB_TYPE_REMOVED:
{
if(oItem == GetObjectByTag("sItemTag")) // sItemTag is simply the tag of your junk item in quotes " "
{
SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);

CreateItemOnObject(sTemplate, OBJECT_SELF, nQuantity);

ActionSpeakString("*SUCCESS* You found a secret compartment in the chest.");
}
else return;
}
}

}

It would be best to use a unique junk item tag :innocent:

Modifié par Morbane, 02 mai 2012 - 07:27 .


#23
Alupinu

Alupinu
  • Members
  • 528 messages

kevL wrote...

lol, my latest trip to hell was yesterday, when I was cleaning out and backing up my campaign and module folders ( lost the association of module <-> campaign ), and then accidentally clicked X on the CampaignScripts tab .....

/ot


Ouch! LOL, that campaign editor can have a short but very steep learning curve. Trust me I know…
 
Thanks a third time Morbane for once again stepping up to the plate. I’ll have to make sure you are in my credits for your unselfish contributions.