Aller au contenu

Photo

Test script


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

#1
PJ156

PJ156
  • Members
  • 2 988 messages
Can I report the value of an integer to the text box as it increments.

I have an on damaged script which updates to count critters dying but its not firing the journal update at the end. I am wanting to see if the integer is counting up or not.

PJ

#2
Morbane

Morbane
  • Members
  • 1 883 messages
it should be in ondeath then - possibly at the top so the final death event happens after the counter.

#3
kevL

kevL
  • Members
  • 4 075 messages
sure PJ, on the line below the line that increments the iInteger, put

SendMessageToPC(GetFirstPC(FALSE), "Current value : " + IntToString(iInteger));


note that to get something like a journal update at the end, the integer usually needs to be stored and accessed in some fashion ... on the Area or the PC, even a handy plot-barrel,

& like Mor says, onDeath would likely be a better place to count up the deceased:

--- pseudo code onDeath ---
getLocalint(obarrel, "idead")
idead = idead + 1;
setLocalint(obarrel, "idead", idead)
// paranoia; re-get the integer to display directly from the barrel/area/pc:
getLocalint(obarrel, "idead")
SendMessageToPC(GetFirstPC(FALSE), "Current value : " + IntToString(iInteger));

// run the journal update after
if (idead >= 10) Do Journal .....

#4
PJ156

PJ156
  • Members
  • 2 988 messages
Thanks KevL that is really useful. I have tried and semi succeeded to fix the script but I have al the tools now.

I went to on damaged because I have had so much trouble with on death, where and npc deals the killing blow. I think this is bypassed to come degree by using the barrel and not calling the PC as get last killer.
Send message to PC is a good tool. I searched integer in the script assist but came u with nothing. I guess it helps to know what you are looking for.

Thanks again to you and Morbane for your responses.

PJ

#5
kevL

kevL
  • Members
  • 4 075 messages
yeh np.

onDeath isn't as troublesome as it sometimes seems, if it's restricted to 'instant' things .. ymmv.


i'd just like to add that there's a lot of loose ends in my pseudo-code, like

if (idead >= 10 && !journal_done) Do Journal ....


and, like you say, I don't know if you're dealing with just PC killers, the PC faction as a whole, or maybe it doesn't matter who the slayer(s) are

anyway, there's some tricks :)

#6
Morbane

Morbane
  • Members
  • 1 883 messages
Ya - factions can help with that

and a factionmember loop to exclude non-pc-related killers

#7
PJ156

PJ156
  • Members
  • 2 988 messages
I am interested in this some more if we can expand it a bit. My problem with ondeath is the somone else killed the bad guy so it does not fire.

I started out using Getlastkiller(); and had all sorts of issues. Especially where a conversation or journal has to fire on death. I am at the point where I will not trust any plot relevant scripts to this issue.

I am designing for SP but with a large team od npc's. What I have had feedback on is that there is a bigger problem again if a summoned creature does the deed.

What I do now, and it seems to work is manipulate an object, like KevL suggested. I take an npc or ipont and treat them as an object. I dont use getlastkiller or any other script to identify the PC I simply get the object and manupulate that (add integers etc). That seems to be much more stable. When I update a journal I GetfirstPC () and make the changes I want to.

What is the best way to create a stable/reliable on death script.

I am pretty new to scripting and have relied on Lilac soul and the generosity of M.Reider a lot so to date I have created scripts but I have learned very little about scripting.

Therefore please forgive any ignorance portrayed in the text above :)

PJ

Modifié par PJ156, 11 mai 2012 - 06:32 .


#8
kevL

kevL
  • Members
  • 4 075 messages
// 'kl_countdead' - onDeath script that counts only party kills
          and updates the Journal.

void main()
{
  // this sends messages to the controlled character of the FirstPC:
  // ! only for debug only !
  object oDebug = GetFirstPC(FALSE);
  SendMessageToPC(oDebug, "the deceased : " + GetName(OBJECT_SELF));

  object oKiller = GetLastKiller();
  SendMessageToPC(oDebug, "the Killer is : " + GetName(oKiller));

  // note, if the Name is blank you can use GetTag() or even check for blank
  // tags/names and insert your own string ... not as handy as using GetName
  // or GetTag tho.

  object oMaster = GetMaster(oKiller);
  while (GetIsObjectValid(oMaster))
  {
    oKiller = oMaster;
    SendMessageToPC(oDebug, "the Master is : " + GetName(oMaster));

    // this checks if, eg, a henchman has a summons
    oMaster = GetMaster(oMaster);
  }
//  else {oKiller = oKiller}  // <- don't need or use this, it's just to help
                // ya figure out what's going on above.

  // notice that the && logic here tends to be confusing (in colloquial
  // parlance you'd think it would be OR but *both* expression need to
  // evaluate False to stop the script)
  if (!GetIsOwnedByPlayer(oKiller) && !GetIsRosterMember(oKiller))
  {
    SendMessageToPC(oDebug, ". oKiller was not in the party");
    return;  // stop.
  }

  // we now know that oKiller has to be a PC-faction member, for the rest of
  // this script. ( But note, this is where MultiPlayer/ MultiParty scripting
  // could get messy. )

  // these two lines would get the actual MainPC even when a companion or
  // associate is the killer; but since my test showed that the journal was
  // getting updated without them, can probably leave these out:
//  oKiller = GetFactionLeader(oKiller);  // <- turns oKiller into the
                      // controlled character (in SP).
//  oKiller = GetOwnedCharacter(oKiller);  // <- turns the controlled object
                      // into the MainPC.

  // supernote: GetIsPC() means GetIsPlayerControlled in NwN2. In other words,
  // all those checks that are strewn about for GetIsPC() will return TRUE if
  // player is controlling, say, a familiar ... not really what we think of as
  // a 'PC' Something to be mindful of


  // don't bother if the Quest is already done:
  int iJournalDone = GetJournalEntry("jt_killz", oKiller);
  // stop the presses! The integer must be set below according to whatever #
  // is assigned in the journal that indicates 'quest done'
  if (iJournalDone >= 1)
  {
    SendMessageToPC(oDebug, ". Quest is complete already.");
    return;  // stop.
  }

  // GetNearestObjectByTag searches through only the current area,
  // GetObjectByTag would search every area in the module. So let's keep it
  // short & simple:
  object oBarrel = GetNearestObjectByTag("unique_barrel_tag", OBJECT_SELF, 1);

  // i put all the parameters above, but only the tag is necessary, and of
  // course the barrel should be Plot (and in the area that the killing is
  // done, unless you're using GetObjectByTag see above).

  int iDeadCount = GetLocalInt(oBarrel, "dead_count");
  // quick form of +1
  iDeadCount ++;  // or, iDeadCount += 1;
          // or, ++ iDeadCount;
          // or iDeadCount = iDeadCount + 1;
          // coders like to have lots of ways of adding "1" .......
  SendMessageToPC(oDebug, "the current dead_count is : "
      + IntToString(iDeadCount));

//  for (iDeadCount; iDeadCount+1; iDeadCount++)
//  {
//    ++ iDeadCount
//  }
// <- facepalm!!! (ignore)

  if (iDeadCount >= 10)
  {
    SendMessageToPC(oDebug, "Quest complete, the Journal gets updated.");

    AddJournalQuestEntry("jt_killz", 1, oKiller);
    int iXp = GetJournalQuestExperience("jt_killz");

    // gives Quest Xp to all companions & PC
    object oPartyPC = GetFirstFactionMember(oKiller, FALSE);
    while (GetIsObjectValid(oPartyPC))
    {
      GiveXPToCreature(oPartyPC, iXp);
      oPartyPC = GetNextFactionMember(oKiller, FALSE);
    }
  }
  // update the barrel:
  else
  {
    SendMessageToPC(oDebug, "Quest incomplete, kill some more!");

    SetLocalInt(oBarrel, "dead_count", iDeadCount);
  }
}


I tested this in an area w/ 15 goblins, all w/ the script in the onDeath. The barrel was Plot, Static, and had 10 hp. My party had two companions, and an animal companion plus a summoned water elemental. The readout was all there and the journal got updated no matter who made the kills, xp was awarded to at least my MainPC. It didn't seem to matter which character was controlled

I've found two hard parts to scripting (aside from logic that can go as far as you could ever imagine). One, learning what functions are available and where they are & how to find them and what they mean. Two, accounting for the complex minutia of what's possible in NwN2, hence taking the time to test, retest, and write tight scripts that don't let anything fall through unnoticed (an example is the GetMaster stuff above). Pinpointing party and player characters is particularly difficult, there are at least 12 functions that deal with that ....

uhm, three. don't lose it when your perfect script isn't doing what you'd expect it to; have a coffee instead.

#9
Morbane

Morbane
  • Members
  • 1 883 messages
 KevL - your aptitude is indeed impressive - great logic in there!
{ copy/paste (for reference) }

:D

#10
PJ156

PJ156
  • Members
  • 2 988 messages
Thank you KevL,

I will put that into the editor and have a good look at that,

PJ

#11
kevL

kevL
  • Members
  • 4 075 messages
i Just seen a hole in the script posted above. what if a RosterMember is not currently in the party but uhm, freelancing nearby? The party could get credited with a kill ...

Lol