Aller au contenu

Photo

Surrender script?


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

#1
TrekSL

TrekSL
  • Members
  • 32 messages
OK, I'm being a plonker - all I want to do during a fight is get the opposing npc to switch faction to the player again and 'yield' by starting a conversation after he's lost some health... Unfortunately, he fights to the death... what have I done wrong??

#2
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
Function - SurrenderToEnemies

#3
TrekSL

TrekSL
  • Members
  • 32 messages
suspect I've gone blind. Spent an hour looking in the lexicon for something like that!

#4
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
There is also the SetIsTemporaryFriend function which can be set to either a limited amount of time or permanent. And I suspect, though I may be wrong, that with either of these functions it is possible to kill the NPC before they get to be friendly. So you might want to make sure their "immortal" box is checked.

#5
henesua

henesua
  • Members
  • 3 863 messages
How does one get the functionality of SurrenderToEnemies but for less time than 3 minutes?

#6
GhostOfGod

GhostOfGod
  • Members
  • 863 messages

henesua wrote...

How does one get the functionality of SurrenderToEnemies but for less time than 3 minutes?



SetIsTemporaryFriend

#7
TSMDude

TSMDude
  • Members
  • 865 messages
You know i wrote this whole freaking script not knowing this was in here...I feel dunderheadish now....

#8
henesua

henesua
  • Members
  • 3 863 messages
I have not had much success with SetIsTemporaryFriend ending combat. I'll try some more experiments.

#9
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages

henesua wrote...

I have not had much success with SetIsTemporaryFriend ending combat. I'll try some more experiments.


I dont think it stops combat.   If you do not Clear the actions of the Characters involved,  They will still wack each other.   In that case the rep wil most likely get adjusted right back to hostile.  That would be my guess anyway.  

#10
GhostOfGod

GhostOfGod
  • Members
  • 863 messages

henesua wrote...

I have not had much success with SetIsTemporaryFriend ending combat. I'll try some more experiments.


You will need to do a ClearAllActions(TRUE);, for both the player and the NPC, at the same time. As well as any of the players henchmen etc. It's not nearly as simple as using the function Lightfoot suggested. But if you need a specific amount of time this might be the way to go.

Modifié par GhostOfGod, 20 juillet 2011 - 09:10 .


#11
henesua

henesua
  • Members
  • 3 863 messages
Thanks. I'll fiddle more with this. I had only been clearing all actions for the NPC. Perhaps that was my problem. It would be good to figure this out and create a custom function that I can use to replace the surrender function.

#12
henesua

henesua
  • Members
  • 3 863 messages
FYI - this seems to work with one enemy present


SetCommandable(TRUE, oPC);
SetCommandable(TRUE, oEnemy);
AssignCommand(oPC, ClearAllActions(TRUE));
SetIsTemporaryFriend(oEnemy, oPC, TRUE, fTime);
AssignCommand(oEnemy, ClearAllActions(TRUE));
SetIsTemporaryFriend(oPC, oEnemy, TRUE, fTime);


But the full function is failing, and I can't find the error.

http://pastebin.com/Dxx3V5ST

Modifié par henesua, 27 juillet 2011 - 05:53 .


#13
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
This is what I came up with. Tested and seems to be working fine. There might be a better way to do it though. Hopefully it can help you.


void StopFactionCombat(object oPC, object oEnemy)
{
    int iNth = 1;
    object oCombatant = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oPC, iNth);
    object oMember;
    while (GetIsObjectValid(oCombatant))
    {
        if (GetFactionEqual(oEnemy, oCombatant))
        {
            oMember = GetFirstFactionMember(oPC, FALSE);
            while (GetIsObjectValid(oMember))
            {
                if (GetCurrentAction(oMember) == ACTION_ATTACKOBJECT)
                AssignCommand(oMember, ClearAllActions(TRUE));
                if (GetCurrentAction(oCombatant) == ACTION_ATTACKOBJECT)
                AssignCommand(oCombatant, ClearAllActions(TRUE));
                SetIsTemporaryFriend(oMember, oCombatant, FALSE);
                oMember = GetNextFactionMember(oPC, FALSE);
            }
        }
        iNth++;
        oCombatant = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oPC, iNth);
    }
}
void main()
{
    object oPC = GetLastDamager(OBJECT_SELF);
    object oEnemy = OBJECT_SELF;
    if (GetCurrentHitPoints(OBJECT_SELF) < 4)
    StopFactionCombat(oPC, oEnemy);
}


P.S. Using the GetFirst/NextFactionMember functions works fine for single player as well since associates are considered faction members.

Modifié par GhostOfGod, 27 juillet 2011 - 10:09 .


#14
henesua

henesua
  • Members
  • 3 863 messages
Thanks GoG.

You did not use GetNearestEnemy as I did. Rather you are simply going through all nearby creatures. Is there something wrong with the GetNearestEnemy function?

Curious as to your thinking here.

#15
GhostOfGod

GhostOfGod
  • Members
  • 863 messages
Honestly, I just didn't know there was a "GetNearestEnemy" function. I've never used it. I just tried to look for it in nw_i0_generic and can't find it though it is on the list of functions.

#16
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages

henesua wrote...

FYI - this seems to work with one enemy present


SetCommandable(TRUE, oPC);
SetCommandable(TRUE, oEnemy);
AssignCommand(oPC, ClearAllActions(TRUE));
SetIsTemporaryFriend(oEnemy, oPC, TRUE, fTime);
AssignCommand(oEnemy, ClearAllActions(TRUE));
SetIsTemporaryFriend(oPC, oEnemy, TRUE, fTime);


But the full function is failing, and I can't find the error.

http://pastebin.com/Dxx3V5ST


There are a couple of errors in your script.  mainly around the ++ operator.

Line34: if (++x==max) break;

should be: if (x++ ==max) break;
make sure you have a space between the ++ and ==. it is not need in this case but does help advoid anbiguity.

You have the same problem on lines: 64, 67 and 77, with the ++ operator on the wrong side of the var you are trying to increase.

...
As to the use of GetNearestEnemy vs GetNearestCreature, I see the use of GetNearestCreature easier to use in this case just because you are not changing the state of the object being a creature or not in the script. The script is however changing there state of being an enemy or not. Sometimes it is hard to tell if changes like this take place while the script is running or wait untill after the script is finished to take effect. Therefore the loop through the creatures is more strightforward then the loop through enemies.

#17
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages

GhostOfGod wrote...

Honestly, I just didn't know there was a "GetNearestEnemy" function. I've never used it. I just tried to look for it in nw_i0_generic and can't find it though it is on the list of functions.



It is in:    X0_I0_ENEMY

it is in the lower branches of the nw_i0_generic includes.  here is the include path from there. 

"nw_i0_generic" > "x0_i0_anims">"x0_i0_walkway">"x0_i0_spawncond">"x0_i0_combat"> "x0_i0_talent"> "x0_inc_generic"> "x0_i0_equip">" x0_i0_enemy"

Modifié par Lightfoot8, 27 juillet 2011 - 06:09 .


#18
GhostOfGod

GhostOfGod
  • Members
  • 863 messages

Lightfoot8 wrote...

GhostOfGod wrote...

Honestly, I just didn't know there was a "GetNearestEnemy" function. I've never used it. I just tried to look for it in nw_i0_generic and can't find it though it is on the list of functions.



It is in:    X0_I0_ENEMY

it is in the lower branches of the nw_i0_generic includes.  here is the include path from there. 

"nw_i0_generic" > "x0_i0_anims">"x0_i0_walkway">"x0_i0_spawncond">"x0_i0_combat"> "x0_i0_talent"> "x0_inc_generic"> "x0_i0_equip">" x0_i0_enemy"


Ah ha! Thanks L8.

#19
henesua

henesua
  • Members
  • 3 863 messages
Lightfoot, putting the ++ operator on the left side of a variable in an expression increments the variable before the expression is evaluated. Putting it on the right increments after the expression is evaluated.

that said I have not tested to see whether NWN operates this way. Typically however this is how it works in other C flavors.

Thanks for the word on GetNearest Enemies... I'll get to work on that.

#20
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages

henesua wrote...

Lightfoot, putting the ++ operator on the left side of a variable in an expression increments the variable before the expression is evaluated. Putting it on the right increments after the expression is evaluated.

that said I have not tested to see whether NWN operates this way. Typically however this is how it works in other C flavors.


I Just tested it in NWScript.  You are correct I does work that way.   Thanks,  for the lesson.    

#21
henesua

henesua
  • Members
  • 3 863 messages
Not a problem. You've given me many more. Thanks for your frequent input.

#22
henesua

henesua
  • Members
  • 3 863 messages
The critical difference between our scripts turned out to be that I am using the decay property of the SetIsTemporaryFriend function.

As soon as I increased the time of "friendship" that I was sending to the function, it successfully stopped combat. The problem is in that you need to give more time for "friendship" than you actually get. This is due to the way the friendship decays. It appears to decay from the moment it is adjusted, rather than after the time delay you give for friendship.

Also GetNearestEnemy works.

[EDIT]
Nevermind... I found some weirdness. (1) I SetIsTemporaryFriend twice on oEnemy which seemed to cause problems. and (2) the loop was ending early.

Both of these are fixed and now "friendship" appears to be decaying properly.

Modifié par henesua, 29 juillet 2011 - 04:15 .


#23
henesua

henesua
  • Members
  • 3 863 messages
 I fixed my stop combat function. It no longer skips creatures nor does it SetIsTemporaryFriend more than once on a creature. With these fixes it does exactly what i wanted: to stop combat, but with a limited duration on the faction change. Only creatures within 10 meters are affected. You can also limit the function to only stopping combat for one specific enemy of a given PC.

***EDIT***  removed MULTIPLAYER constant so that this functions for other people than myself
http://pastebin.com/pytSBPmE

void StopCombat(object oPC1, object oEnemy, int nRounds, int bAll = FALSE)
{
    float fTime  = RoundsToSeconds(nRounds);

    int x   = 1; // iterations of combatant loop
    int y   = 0; // iterations of pc loop
    int z; // iterations of associate type
    int max = x+50; // maximum combatants of each character to neutralize

    object oPC  = GetFirstFactionMember(oPC1); // get first member of party
    object oNPC; // associates of oPC
    object oCombatant; // additional enemies of oPC or oNPC

    while (GetIsObjectValid(oPC))
    {
        // targeted enemy of PC
        SetCommandable(TRUE, oPC);
        SetCommandable(TRUE, oEnemy);
        AssignCommand(oPC, ClearAllActions(TRUE));
        AssignCommand(oEnemy, ClearAllActions(TRUE));
        SetIsTemporaryFriend(oPC, oEnemy, TRUE, fTime);
        SetLocalInt(oEnemy, "STOPPED_COMBAT", TRUE);
        DelayCommand(1.0, DeleteLocalInt(oEnemy, "STOPPED_COMBAT"));
        if (bAll)
        {
          // next loop through all remaining enemies of oPC
          x = 1;
          oCombatant   = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oPC, x);
          while (GetIsObjectValid(oCombatant) && x < max)
          {
            if (!GetLocalInt(oCombatant, "STOPPED_COMBAT") && GetDistanceBetween(oPC, oCombatant) <= 20.0)
            {
                SetLocalInt(oCombatant, "STOPPED_COMBAT", TRUE);
                DelayCommand(1.0, DeleteLocalInt(oCombatant, "STOPPED_COMBAT"));
                SetCommandable(TRUE, oCombatant);
                if(GetIsInCombat(oCombatant))
                    AssignCommand(oCombatant, ClearAllActions(TRUE));
                SetIsTemporaryFriend(oPC, oCombatant, TRUE, fTime);
            }
            oCombatant   = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oPC, ++x);
          }
        }

        // loop through all Associates of oPC
        for (z = 1; z <= 5; z ++)
        {
            int w = 1;
            oNPC = GetAssociate(z, oPC, w);
            while (GetIsObjectValid(oNPC))
            {
                // first enemy of NPC
                SetCommandable(TRUE, oNPC);
                AssignCommand(oNPC, ClearAllActions(TRUE));
                AssignCommand(oEnemy, ClearAllActions(TRUE));
                SetIsTemporaryFriend(oEnemy, oNPC, TRUE, fTime);
                SetIsTemporaryFriend(oNPC, oEnemy, TRUE, fTime);
                if(bAll)
                { // next loop through all remaining enemies of NPC
                    x = 1;
                    oCombatant = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oNPC, x);
                    while (GetIsObjectValid(oCombatant) && x < max)
                    {

                        if (!GetLocalInt(oCombatant, "STOPPED_COMBAT") && GetDistanceBetween(oPC, oCombatant) <= 20.0)
                        {
                            SetLocalInt(oCombatant, "STOPPED_COMBAT", TRUE);
                            DelayCommand(1.0, DeleteLocalInt(oCombatant, "STOPPED_COMBAT"));
                            SetCommandable(TRUE, oCombatant);
                            if(GetIsInCombat(oCombatant))
                                AssignCommand(oCombatant, ClearAllActions(TRUE));
                            SetIsTemporaryFriend(oCombatant, oNPC, TRUE, fTime);
                            SetIsTemporaryFriend(oNPC, oCombatant, TRUE, fTime);
                        }
                        oCombatant   = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oPC, ++x);
                    }
                }
                oNPC = GetAssociate(z, oPC, ++w);
            }
        }
        // Get Next PC Party Member
        oPC = GetNextFactionMember(oPC1);
    } // loop through PC party members
}

Modifié par henesua, 29 juillet 2011 - 05:47 .