Portal-Zone Gothic-Zone Gothic II-Zone Gothic 3-Zone Gothic 4-Zone Modifikationen-Zone Download-Zone Foren-Zone RPG-Zone Almanach-Zone Spirit of Gothic

 

Ergebnis 1 bis 6 von 6
  1. Beiträge anzeigen #1 Zitieren
    Warrior Avatar von Czudak
    Registriert seit
    Sep 2015
    Beiträge
    415
     
    Czudak ist offline

    Npc_ChangeAttribute not causing instant death.

    Howdy, people.

    I have a problem of delicate scripting nature. I created a function that's supposed to enable the player to execute a "sneak attack"; it's rather basic, but it works. The code for it is below:

    func void CheckForBackstabDamage(var C_Npc other,var C_Npc self)
    {
    if(C_NpcIsHero(other) && (!Npc_CanSeeNpc(self,other) || Npc_IsInState(self,ZS_Sleep) || Npc_IsInState(self,ZS_Sleep_Deep)) && C_BodyStateContains(other,BS_HIT) && (Npc_GetTalentSkill(other,NPC_TALENT_SNEAK) == TRUE) && Npc_IsInFightMode(other,FMODE_MELEE) && !C_NpcIsUndead(self) && !C_NpcIsGolem(self) && !Npc_IsInState(self,ZS_Attack) && !Npc_IsInState(self,ZS_MM_Attack))
    {
    Backstab = other.attribute[ATR_DEXTERITY] * 3;
    Npc_ChangeAttribute(self,ATR_HITPOINTS,-Backstab);
    PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
    if(Npc_IsDead(self))
    {
    B_GiveDeathXp(other,self);
    };
    };
    };
    I took the Npc_ChangeAttribute bit from B_MagicHurtNpc function. It's all dandy and stuff, but if the Backstab value exceeds the victim's current Health, instead of instantly dying, it barks back and only then falls down lifelessly. Sometimes, it even readies their weapon, barks back, and then perishes.

    I tried to apply AI_StopProcessInfos(self), or Npc_ClearAIQueue(self), or AI_PlayAni(other,"T_DEAD"), alone and in mixed configurations, but no dice.

    Does anyone know how to script it so the victim would simply die when they are supposed to die, with no "Just you wait, sumbitch!" remark before realizing they are dead?
    Geändert von Czudak (11.01.2020 um 19:55 Uhr)

  2. Beiträge anzeigen #2 Zitieren
    Auserwählter Avatar von Nincompoop
    Registriert seit
    Aug 2006
    Ort
    Berlin
    Beiträge
    6.346
     
    Nincompoop ist offline
    What do you mean by "exceeds the victim's current Health"? Does that include dealing the exact same damage as their current health? Otherwise you could check if the damage is greater and then set the hp to exactly zero.

    How is the sneak attack executed? Is it just a check when performing a normal attack? In that case the check might simply be too late. So the attack is processed and causes the target to draw his weapon and THEN your check happens and he gets killed.
    So it would be interesting to know in which file and at which position your function is called.

  3. Beiträge anzeigen #3 Zitieren
    Warrior Avatar von Czudak
    Registriert seit
    Sep 2015
    Beiträge
    415
     
    Czudak ist offline
    Zitat Zitat von Nincompoop Beitrag anzeigen
    What do you mean by "exceeds the victim's current Health"? Does that include dealing the exact same damage as their current health? Otherwise you could check if the damage is greater and then set the hp to exactly zero.

    How is the sneak attack executed? Is it just a check when performing a normal attack? In that case the check might simply be too late. So the attack is processed and causes the target to draw his weapon and THEN your check happens and he gets killed.
    So it would be interesting to know in which file and at which position your function is called.
    Right. I knew I forgot about something.

    I think you might be on something. The backstab check requires the player to be in the "hitting" bodystate [it's C_BodyStateContains(other,BS_HIT) in the function from the first post], and the whole check was inserted into the B_ASSESSDAMAGE script. I will paste it here, via the quote code, so it would be readable better. The call for my "backstab" check is third from the top.

    func void B_AssessDamage()
    {
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Greg_Nw))
    {
    if((B_Greg_ComesToDexter_OneTime == TRUE) && Npc_IsPlayer(other) && !Npc_KnowsInfo(other,Dia_Addon_Greg_NW_CaughtDexter) && !Npc_KnowsInfo(other,Dia_Addon_Greg_NW_CaughtDexter2) && !Npc_KnowsInfo(other,Dia_Addon_Greg_NW_WodennNu))
    {
    return;
    };
    };
    B_ArrowBonusDamage(other,self);
    CheckForBackstabDamage(other,self);
    if(Npc_IsInState(self,ZS_ReactToDamage))
    {
    B_Attack(self,other,AR_ReactToDamage,0);
    };
    if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Quarhodron)) || (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Rhademes)))
    {
    B_GhostSpecialDamage(other,self);
    return;
    };
    if(Npc_IsPlayer(other) && (self.guild == GIL_FRIENDLY_ORC))
    {
    B_SetAttitude(self,ATT_HOSTILE);
    };
    B_BeliarsWeaponSpecialDamage(other,self);
    if(self.aivar[AIV_ArenaFight] == AF_AFTER)
    {
    self.aivar[AIV_ArenaFight] = AF_AFTER_PLUS_DAMAGE;
    };
    if(self.aivar[AIV_EnemyOverride] == TRUE)
    {
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Raven))
    {
    self.aivar[AIV_EnemyOverride] = FALSE;
    Npc_ExchangeRoutine(self,"WaitForPlayer");
    Raven_Awaken = TRUE;
    };
    };
    if(Npc_IsInState(self,ZS_Attack))
    {
    if(Npc_IsPlayer(other) && (self.npcType == NPCTYPE_FRIEND))
    {
    return;
    };
    if(Npc_IsPlayer(other) && (self.aivar[AIV_PartyMember] == TRUE))
    {
    return;
    };
    if(Hlp_GetInstanceID(other) != self.aivar[AIV_LASTTARGET])
    {
    if((self.aivar[AIV_HitByOtherNpc] == Hlp_GetInstanceID(other)) || (Hlp_GetInstanceID(other) != Hlp_GetInstanceID(hero)))
    {
    Npc_SetTarget(self,other);
    }
    else
    {
    self.aivar[AIV_HitByOtherNpc] = Hlp_GetInstanceID(other);
    };
    };
    return;
    };
    if(B_AssessEnemy())
    {
    return;
    };
    if(!Npc_IsPlayer(other) && (other.aivar[AIV_ATTACKREASON] == AR_NONE))
    {
    B_Attack(self,other,AR_NONE,0);
    return;
    };
    if(Npc_IsInFightMode(other,FMODE_MELEE) || Npc_IsInFightMode(other,FMODE_FIST) || Npc_IsInFightMode(other,FMODE_NONE))
    {
    if((Npc_GetAttitude(self,other) == ATT_FRIENDLY) || ((self.npcType == NPCTYPE_FRIEND) && Npc_IsPlayer(other)))
    {
    if(!Npc_IsInState(self,ZS_ReactToDamage))
    {
    Npc_ClearAIQueue(self);
    B_ClearPerceptions(self);
    AI_StartState(self,ZS_ReactToDamage,0,"");
    return;
    };
    };
    };
    B_Attack(self,other,AR_ReactToDamage,0);
    };

  4. Beiträge anzeigen #4 Zitieren
    Auserwählter Avatar von Nincompoop
    Registriert seit
    Aug 2006
    Ort
    Berlin
    Beiträge
    6.346
     
    Nincompoop ist offline
    hm, seems to be the right place, unless somehow one of the perceiptions get triggered first (fight sound or something) but I doubt it.

    You could try adding a check in the B_AssessDamage to see if the NPC HP are 0 and then add a return statement there (return from the B_AssessDamage, not from your own function).


    btw: For readability, the code block is better than the quote ('#' - Symbol, or [code][*/code] (without the asterisk)).

  5. Beiträge anzeigen #5 Zitieren
    Veteran Avatar von N1kX
    Registriert seit
    Aug 2018
    Ort
    Serov
    Beiträge
    643
     
    N1kX ist offline
    Hello. Try to make a check on the damage and health of the target, and if the target will die translate it into a state of death
    Code:
    //old version
    func void CheckForBackstabDamage(var C_Npc other,var C_Npc self)
    {
        if(C_NpcIsHero(other) && (!Npc_CanSeeNpc(self,other) || Npc_IsInState(self,ZS_Sleep) || Npc_IsInState(self,ZS_Sleep_Deep)) && C_BodyStateContains(other,BS_HIT) && (Npc_GetTalentSkill(other,NPC_TALENT_SNEAK) == TRUE) && Npc_IsInFightMode(other,FMODE_MELEE) && !C_NpcIsUndead(self) && !C_NpcIsGolem(self) && !Npc_IsInState(self,ZS_Attack) && !Npc_IsInState(self,ZS_MM_Attack))
        {
            Backstab = other.attribute[ATR_DEXTERITY] * 3;
            Npc_ChangeAttribute(self,ATR_HITPOINTS,-Backstab);
            PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
            if(Npc_IsDead(self))
            {
                B_GiveDeathXp(other,self);
            };
        };
    };
    
    
    
    //new version
    func void CheckForBackstabDamage(var C_Npc other,var C_Npc self)
    {
        if(C_NpcIsHero(other) && (!Npc_CanSeeNpc(self,other) || Npc_IsInState(self,ZS_Sleep) || Npc_IsInState(self,ZS_Sleep_Deep)) && C_BodyStateContains(other,BS_HIT) && (Npc_GetTalentSkill(other,NPC_TALENT_SNEAK) == TRUE) && Npc_IsInFightMode(other,FMODE_MELEE) && !C_NpcIsUndead(self) && !C_NpcIsGolem(self) && !Npc_IsInState(self,ZS_Attack) && !Npc_IsInState(self,ZS_MM_Attack))
        {
            Backstab = other.attribute[ATR_DEXTERITY] * 3;
            if(Backstab >= self.attribute[ATR_HITPOINTS])
            {
                self.attribute[ATR_HITPOINTS] = 0;
                PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
                B_GiveDeathXp(other,self);
                AI_PlayAniBS(self, "T_DEAD", BS_DEAD);
                if(self.guild < GIL_SEPERATOR_HUM)
                {
                    B_Say(self,other,$DEAD);
                };
                AI_StartState(self,ZS_DEAD,0,"");
            }
            else
            {
                Npc_ChangeAttribute(self,ATR_HITPOINTS,-Backstab);
                PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
            };
        };
    };
    Wrote in haste, correct errors if that
    Geändert von N1kX (12.01.2020 um 08:37 Uhr)

  6. Beiträge anzeigen #6 Zitieren
    Warrior Avatar von Czudak
    Registriert seit
    Sep 2015
    Beiträge
    415
     
    Czudak ist offline
    Zitat Zitat von Nincompoop Beitrag anzeigen
    hm, seems to be the right place, unless somehow one of the perceiptions get triggered first (fight sound or something) but I doubt it.

    You could try adding a check in the B_AssessDamage to see if the NPC HP are 0 and then add a return statement there (return from the B_AssessDamage, not from your own function).


    btw: For readability, the code block is better than the quote ('#' - Symbol, or [code][*/code] (without the asterisk)).
    Zitat Zitat von N1kX Beitrag anzeigen
    Hello. Try to make a check on the damage and health of the target, and if the target will die translate it into a state of death
    Code:
    //old version
    func void CheckForBackstabDamage(var C_Npc other,var C_Npc self)
    {
        if(C_NpcIsHero(other) && (!Npc_CanSeeNpc(self,other) || Npc_IsInState(self,ZS_Sleep) || Npc_IsInState(self,ZS_Sleep_Deep)) && C_BodyStateContains(other,BS_HIT) && (Npc_GetTalentSkill(other,NPC_TALENT_SNEAK) == TRUE) && Npc_IsInFightMode(other,FMODE_MELEE) && !C_NpcIsUndead(self) && !C_NpcIsGolem(self) && !Npc_IsInState(self,ZS_Attack) && !Npc_IsInState(self,ZS_MM_Attack))
        {
            Backstab = other.attribute[ATR_DEXTERITY] * 3;
            Npc_ChangeAttribute(self,ATR_HITPOINTS,-Backstab);
            PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
            if(Npc_IsDead(self))
            {
                B_GiveDeathXp(other,self);
            };
        };
    };
    
    
    
    //new version
    func void CheckForBackstabDamage(var C_Npc other,var C_Npc self)
    {
        if(C_NpcIsHero(other) && (!Npc_CanSeeNpc(self,other) || Npc_IsInState(self,ZS_Sleep) || Npc_IsInState(self,ZS_Sleep_Deep)) && C_BodyStateContains(other,BS_HIT) && (Npc_GetTalentSkill(other,NPC_TALENT_SNEAK) == TRUE) && Npc_IsInFightMode(other,FMODE_MELEE) && !C_NpcIsUndead(self) && !C_NpcIsGolem(self) && !Npc_IsInState(self,ZS_Attack) && !Npc_IsInState(self,ZS_MM_Attack))
        {
            Backstab = other.attribute[ATR_DEXTERITY] * 3;
            if(Backstab >= self.attribute[ATR_HITPOINTS])
            {
                self.attribute[ATR_HITPOINTS] = 0;
                PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
                B_GiveDeathXp(other,self);
                AI_PlayAniBS(self, "T_DEAD", BS_DEAD);
                if(self.guild < GIL_SEPERATOR_HUM)
                {
                    B_Say(self,other,$DEAD);
                };
                AI_StartState(self,ZS_DEAD,0,"");
            }
            else
            {
                Npc_ChangeAttribute(self,ATR_HITPOINTS,-Backstab);
                PrintScreen("Sneak attack!",-1,-1,Font_Screen,2);
            };
        };
    };
    Wrote in haste, correct errors if that
    Thank you for your input, fellows! I tried your solutions (combined too), but it didn't work. I need to investigate those "perceptions"; maybe try to disable all perceptions altogether if the requirements for a "sneak attack" happen in the first place, and then calculate the damage and the possibility of death? Or maybe it's not doable with the clean Daedalus and one needs a scripts extender? I will report back once I'm done with pestering people on the other forums!

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
Impressum | Link Us | intern
World of Gothic © by World of Gothic Team
Gothic, Gothic 2 & Gothic 3 are © by Piranha Bytes & Egmont Interactive & JoWooD Productions AG, all rights reserved worldwide