lroumen Posted August 27, 2009 Posted August 27, 2009 Hello everybody. I am currently writing a small mod for myself which involves the following. I have a Djinni cast a spell on me which is done several different times. I store the amount of times in a global variable. Now I would like to have a dialogue with the Djinni to ask how many times he has cast it on me thus far to keep track of it in game rather than by hand. Hence, I would like to get the number from the global variable, but I do not know how to handle this in a dialogue. It works something like this and I was hoping someone could give me a tip. IF ~~ THEN BEGIN CastSpell SAY ~Very well, I will cast a spell on you.~ IF ~~ THEN DO ~ApplySpellRES("MySpell",LastTalkedTo()) CreateVisualEffectObject("SPFLSRIN",Myself) Wait(1) PlaySound("EFF_M38") CreateVisualEffectObject("SPFLESHS",Myself) DestroySelf() IncrementGlobal("MySpellCast","LOCALS",1)~ END then in a different dialogue to ask how often it happened. IF ~~ THEN BEGIN Castingdialogue SAY ~What would you like to know?~ IF ~~ THEN REPLY ~Tell me how often you cast that spell on me~ GOTO Thismany END IF ~~ THEN BEGIN Thismany SAY ~I have cast the spell on you XXX times.~ END Where XXX is the value of Global("MySpellCast","LOCALS"). Is there a good way to implement this other than doing something this? IF ~~ THEN BEGIN Thismany SAY ~Well let me see~ IF ~Global("MySpellCast","LOCALS", 1)~ THEN == SAY ~I have cast the spell on you 1 time.~ IF ~Global("MySpellCast","LOCALS", 2)~ THEN == SAY ~I have cast the spell on you 2 times.~ etcetera END Excuse me for the syntax. It is probably wrong in a few places since I did not thoroughly test or debug it yet. So in conclusion, I was wondering whether the incremented global can be put into the text string rather than having to copy the if statement a lot of times. Thanks in advance
Grim Squeaker Posted August 27, 2009 Posted August 27, 2009 I don't believe so, no. This is kind of gizmo that WeiNGINE is very good at, but the Infinity Engine just can't do.
Wisp Posted August 27, 2009 Posted August 27, 2009 Have a look at the action SetTokenGlobal. It may do what you want.
lroumen Posted August 27, 2009 Author Posted August 27, 2009 Thanks for the responses so far. I thought about tokens but since they are global it may cause problems if I have to keep a counter for two NPCs. SetTokenGlobal does seem to do the thing I am looking for. Now to make it NPC independant if such a thing is possible.
cmorgan Posted August 27, 2009 Posted August 27, 2009 Globals are just that, global, so they are independent of any one NPC - which means if you use SetTokenGlobal, and manipulate a secondary global for the particular NPC, you can track both. Complicated, and someone can probably come up with something better, but the logic goes like this: 1. add an effect to the spell that advances a global, 'numbertimescast" or whatever. 2. access the spell through dialog, so that you can find <GABBER> or PLAYER1 or whatever, and have a global tracking for each NPC. 3. use the [set]TokenGlobal series to transfer that data - you can even set up your own dialog token for it. The end result could create a string like CHAIN ~I have cast my spell <NUM_CAST> times...~ == GENIE IF ~GlobalGT("p1","GLOBAL",0)~ THEN ~<p1> times for <PLAYER1>...~ == GENIE IF ~GlobalGT("p2","GLOBAL",0)~ THEN ~<p2> times for <PLAYER2>...~ == GENIE IF ~GlobalGT("p3","GLOBAL",0)~ THEN ~<p3> times for <PLAYER3>...~ == GENIE IF ~GlobalGT("p4","GLOBAL",0)~ THEN ~<p4> times for <PLAYER4>...~ == GENIE IF ~GlobalGT("p5","GLOBAL",0)~ THEN ~<p5> times for <PLAYER5>...~ == GENIE IF ~GlobalGT("p6","GLOBAL",0)~ THEN ~<p6> times for <PLAYER6>...~ END EXTERN ~GENIE~ answerstate IF ~~ answerstate SAY ~Do you want me to cast it again? It will cost you dearly.~ ++ ~That is nice. Do it again. Cast it on me.~ DO ~IncrementGlobal("p1","GLOBAL",1) + newstate1 + ~NumInPartyLT(3)~ + ~That is nice. Do it again. Cast it on <PLAYER2>.~ DO ~IncrementGlobal("p2","GLOBAL",1) + newstate1 + ~NumInPartyLT(4)~ + ~That is nice. Do it again. Cast it on <PLAYER3>.~ DO ~IncrementGlobal("p3","GLOBAL",1) + newstate1 + ~NumInPartyLT(5)~ + ~That is nice. Do it again. Cast it on <PLAYER4>.~ DO ~IncrementGlobal("p4","GLOBAL",1) + newstate1 + ~NumInPartyLT(6)~ + ~That is nice. Do it again. Cast it on <PLAYER5>.~ DO ~IncrementGlobal("p5","GLOBAL",1) + newstate1 + ~NumInParty(6)~ + ~That is nice. Do it again. Cast it on <PLAYER6>.~ DO ~IncrementGlobal("p6","GLOBAL",1) + newstate1 ++ ~Forget it. i was just asking.~ EXIT The tiering of dialog here means that replies for the player will scale with # players. You might need some more though behind this to get it to be robust enough to deal with swapping party members in and out, probably by creating CHAIN entries that are triggered only if the NPC is both in the party and has a variable set, but the basics are there. Use the spell to increment the # times cast global, a second global to track the usage on a particular NPC. (I actually would recommend rethinking the level of detail here unless you feel it is absolutely imperative, or you are tracking the variable to impose a penalty for mis/overuse- say, perhaps, a -1 to constitution if the spell is cast on a person more than 5 times or something. If you can get away with it, less is more. The more precise you make it, the more difficult it is to deal with mod added NPCs).
lroumen Posted August 27, 2009 Author Posted August 27, 2009 Maybe I misunderstood the use of globals. I thought that the difference between global('var','global',x) and gloval('var','locals',x) was the following. 'locals' is attached to just one cre so you could have the same local for each of the NPCs. 'global' is a unique global that if attached to an npc would result in the same value for another npc. please correct me if I am wrong because that might get me in a bunch of coding problems. The genie summoning happens upon levelup of a certain kit. So the caster will actually be a reallyforcespell type of thing going on when the level increases and then I could make the genie NPC specific by using lastsummonerofmyself(), correct? That should prevent the genie from casting spells on other NPCs by forcetalk abuse. I really appreaciate the example you have given but I am not certain whether I fully understand it. I do get that you currently have the genie cast a spell on any party member, but as I noted above that is not competely the purpose. I hope I have explained it better. I will have to read it more carefully tonight and think about whether I would want to juggle with the player1-6 variables or not. Perhaps it would just be easier to copy the dialogue a bunch of times. I guess I have to think about it some more before I decide what to do.
Wisp Posted August 27, 2009 Posted August 27, 2009 'locals' is attached to just one cre so you could have the same local for each of the NPCs. Almost. But the local variable is set on the genie and not on the party member. You can have "the same" local variable on 6 different genies, but not the same local variable on 1 genie for 6 different people.
cmorgan Posted August 27, 2009 Posted August 27, 2009 Ah, i goty confused by this: I thought about tokens but since they are global it may cause problems if I have to keep a counter for two NPCs. I thought you were trying to keep track of multiple NPCs. Yeah, Wisp is right - by switching my example to LOCALS instead of GLOBAL, you can set multiple different LOCALS and store them on the genie. If you are looking for a straight single-Player1 kit upgrade, no problem - you already have it. If you are lookig for tracking different NPCs who might have the same kit, then adapting my example might get you there. The only thing left to check is are LOCALS persistent if you EscapeAreaDestroy() the Genie. I can't remember if they are or not.
lroumen Posted August 27, 2009 Author Posted August 27, 2009 I am sorry for the confusion. I realise I did not explain everything in my first post. The variable is on the genie? How could I have missed that? If I ever decide to distribute the kit then it would be good if it were robust enough to be used by multiple NPCs. I think it's a good idea for me to puzzle through your suggestions. I'm guessing that locals on one NPC cannot be checked for in the script of another NPC, so I would be better off setting them as global, especially if the kit is for multiple NPCs because the locals on the genie will likely be overwritten since my reallyforcespell (actually it's applyspellres) will summon the same genie. spell effect to advance a global is Modify Global Variable [265], correct?
lroumen Posted August 31, 2009 Author Posted August 31, 2009 I've been juggling my script quite a bit this weekend. Based on a cast at levelup I am currently using "LastSummonerOf(Myself)" to sort out which player (1-6) I am talking to and with six IFs I am able to increment the global for each player. However, if I make a custom NPC with my kit and swap it out of the party, I still have to clear the globals of the current playerX and when the NPC rejoins I will have to put the globals back, if necessary into the correct playerX. I am currently unsure on how to sync this type of thing. Can anybody give me a hint?
lroumen Posted October 22, 2009 Author Posted October 22, 2009 Hi everybody. Some update. I have been bugswapping a lot of my mod and I figured out that I had a lot of work to test and fine-tune before I even got to the token part. Finally I have come to that part and I have been fiddling with the scripting of it, but as of yet not very successfully. For some reason I still cannot get the tokens to work out. I have gotten to the point where I put <LRSWTRAP> into my dialogue as a token to be used ingame. Then the token should be replaced by a variable as determined by a global variable with the same name (also LRSWTRAP). IF OnCreation() THEN RESPONSE #100 SetTokenGlobal("LRSWTRAP","GLOBAL","LRSWTRAP") END Well... using this I didn't get the <LRSWTRAP> to work in my dialogue so I tested the following to see whether the token is being set or not. If I use this I check for the change in the global variable. IF Global("LRINITIATE","GLOBAL",0) Global("LRSWTRAP","GLOBAL",0) THEN RESPONSE #100 SetToken("LRSWTRAP","0") SetGlobal("LRINITIATE","GLOBAL",1) END The result is that when I ask for the global values using CLUA I get that: LRSWTRAP does not exist (thus it is correctly 0) LRINITIATE has the value 1, so apparently the block has been executed. When I trip the dialogue where the token <LRSWTRAP> is called, instead of the string "0", it skips the token altogether eventhough the dialogue file in itself seems to work. Is there a method to directly ask via CLUA what the value of a token is?
Mike1072 Posted October 22, 2009 Posted October 22, 2009 Two things: The SetToken() command is supposed to take a string reference, not a string, so if you instead used SetToken("LRSWTRAP",1079), your line containing the token should display the contents of string 1079 ("Cleric") in place of the token. I didn't notice any problem when testing SetTokenGlobal(). Could you elaborate on how it isn't working?
lroumen Posted October 22, 2009 Author Posted October 22, 2009 I think I misunderstood SetToken. I thought I could put in a string and subsequently have it called in a dialogue portion. I guess since my value is 0 and stringreference 0 has no entry, the token would be empty. Correct? With regard to SetTokenGlobal, this is my sequence: .baf IF OnCreation() THEN RESPONSE #100 SetTokenGlobal("LRSWTRAP","GLOBAL","LRSWTRAP") END .d file BEGIN LRCHAR IF ~True()~ THEN BEGIN INTRODUCTION SAY ~The value of LRSWTRAP is <LRSWTRAP>.~ END However, the speech results in "The value of LRSWTRAP is ." rather than "The value of LRSWTRAP is 0." Could it be that if the global does not exist (since basically I did not initiate it by putting it to 0), the token is not properly set to 0, but defaults to nothing?
Mike1072 Posted October 22, 2009 Posted October 22, 2009 Oh, if you're compiling a .baf, your string might get added to dialog.tlk and turned into a strref anyway, so don't mind me. Checking the compiled .bcs with NI will show you for sure what the strref and associated string the command should have output. I'm not having any problems updating and displaying a token from within a script, so I don't have much else to add right now. IF OnCreation() THEN RESPONSE #100 DisplayString(Myself,87755) // Token LRSWTRAP: "<LRSWTRAP>" SetTokenGlobal("LRSWTRAP","GLOBAL","LRSWTRAP") DisplayString(Myself,87755) // Token LRSWTRAP: "<LRSWTRAP>" SetGlobal("LRSWTRAP","GLOBAL",1072) END IF Global("LRSWTRAP","GLOBAL",1072) THEN RESPONSE #100 SetTokenGlobal("LRSWTRAP","GLOBAL","LRSWTRAP") DisplayString(Myself,87755) // Token LRSWTRAP: "<LRSWTRAP>" SetGlobal("LRSWTRAP","GLOBAL",1073) END IF Global("LRSWTRAP","GLOBAL",1073) THEN RESPONSE #100 SetToken("LRSWTRAP",1079) // Cleric DisplayString(Myself,87755) // Token LRSWTRAP: "<LRSWTRAP>" SetGlobal("LRSWTRAP","GLOBAL",1074) END Output: Token LRSWTRAP: "" Token LRSWTRAP: "0" Token LRSWTRAP: "1072" Token LRSWTRAP: "Cleric"
Recommended Posts
Archived
This topic is now archived and is closed to further replies.