Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPCs cannot use ladders when following the player #136

Merged
merged 1 commit into from Mar 3, 2021
Merged

Conversation

szapp
Copy link
Collaborator

@szapp szapp commented Mar 1, 2021

Describe the bug
NPCs don't use ladders properly when they are following the player.

Expected behavior
NPCs now use ladders properly when they are following the player.

Steps to reproduce the issue

  1. Enter the Free Mine with Gorn.
  2. Let Gorn run off the main platform.

Testing
Run a manual test with test 136.

Additional context
When Gorn runs off the platform, he struggles to come up again. He starts using the ladder, but falls down midways.

ScreenShot_2021_2_20_23_20_25

@AmProsius AmProsius added validation: required This issue needs validation from one of the validators. validation: validated This issue is still present even with Systempack/Union. and removed validation: required This issue needs validation from one of the validators. labels Feb 20, 2021
@szapp szapp changed the title NPCs cannot use ladders during free pathfinding NPCs cannot use ladders when following the player Mar 1, 2021
@szapp
Copy link
Collaborator

szapp commented Mar 1, 2021

I have a fix for followers specifically. I don't know how to fix it for NPCs in general.

func void B_FollowPC_AssessSC()
{
PrintDebugNpc (PD_TA_FRAME, "B_FollowPC_AssessSC");
if (Npc_GetDistToNpc(self,hero) < HAI_DIST_FOLLOWPC)
{
PrintDebugNpc (PD_TA_CHECK, "...SC-Meister jetzt nahe genug!");
B_FullStop (self);
};

changed to

func void B_FollowPC_AssessSC()
{
    PrintDebugNpc       (PD_TA_FRAME,   "B_FollowPC_AssessSC");

    // Disable this perception when climbing a ladder
    if (C_BodyStateContains(self, BS_CLIMB)) {
        return;
    };

    if (Npc_GetDistToNpc(self,hero) < HAI_DIST_FOLLOWPC)
    {
        PrintDebugNpc   (PD_TA_CHECK,   "...SC-Meister jetzt nahe genug!");
        B_FullStop      (self);
    };

@AmProsius
Copy link
Owner Author

I have a fix for followers specifically. I don't know how to fix it for NPCs in general.

We could just rename the issue. I currently don't know a situation in which an NPC has to climb a latter while they run freely.
Or we could open another issue for that.

@szapp
Copy link
Collaborator

szapp commented Mar 1, 2021

We could just rename the issue.

Tried to find a more specific name. (I haven't changed the description of the issue, though.)

I currently don't know a situation in which an NPC has to climb a latter while they run freely.

Gorn in the Free Mine, for example (again). If he falls down and wants to reach the NPC he is targeting above, he will eventually reach the ladder and climb up. If he is interrupted he will continue to fall down. But I could only reproduce this once.

Update I am not so sure how often it would happen that an NPC that is involved in a fight (or otherwise) climbs a ladder. Until we experience that more specifically I would like to leave it at this issue, because I checked and I don't see any way to make it work in general without possibly breaking a mod.

@AmProsius AmProsius merged commit 289a93a into master Mar 3, 2021
@AmProsius AmProsius deleted the bug136 branch March 3, 2021 20:27
@AmProsius AmProsius added this to In Progress in v1.0.0 via automation Mar 3, 2021
@AmProsius AmProsius added this to the v1.0.0 milestone Mar 3, 2021
@AmProsius AmProsius moved this from In Progress to Done in v1.0.0 Mar 3, 2021
@szapp szapp added this to NPC state in Fix templates Mar 17, 2021
@szapp szapp added the impl: hook engine func This issue requires hooking engine functions. label Mar 17, 2021
@pawbuj1981
Copy link

Just checked that issue a minute ago and it does not works properly . ! I have tested on Gothic 1 vanilla with Pc_FighterFM. Again Gothic Mod Fix team had fixed that. I used their code and little change so I will forward solution soon.

@pawbuj1981
Copy link

pawbuj1981 commented Mar 20, 2021

Here is the code, I believe it needs to modify a bit. Also NPCc react on hero being attacked !

{
	PrintDebugNpc(PD_TA_FRAME,"ZS_FollowPC");
	Npc_PercEnable(self,PERC_ASSESSENEMY,B_AssessEnemy);
	Npc_PercEnable(self,PERC_ASSESSPLAYER,B_FollowPC_AssessSC);
	Npc_SetPercTime(self,1);
	self.senses = SENSE_SEE | SENSE_HEAR | SENSE_SMELL;
	Npc_PercEnable(self,PERC_ASSESSDAMAGE,ZS_ReactToDamage);
	Npc_PercEnable(self,PERC_ASSESSCASTER,B_AssessCaster);
	Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
	Npc_PercEnable(self,PERC_ASSESSMURDER,ZS_AssessMurder);
	Npc_PercEnable(self,PERC_ASSESSDEFEAT,ZS_AssessDefeat);
	Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND,B_AssessFightSound);
	Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
	Npc_PercEnable(self,PERC_MOVEMOB,B_MoveMob);
	self.aivar[AIV_ITEMFREQ] = 0;
};

func int ZS_FollowPC_Loop()
{
	if(C_BodyStateContains(hero,BS_CLIMB) && (self.aivar[AIV_ITEMFREQ] == 0))
	{
		hero.wp = Npc_GetNearestWP(hero);
		self.aivar[AIV_ITEMFREQ] = 1;
		AI_SetWalkMode(self,NPC_RUN);
		AI_GotoWP(self,hero.wp);
		return LOOP_CONTINUE;
	}
	else if(C_BodyStateContains(hero,BS_CLIMB) && (self.aivar[AIV_ITEMFREQ] == 1))
	{
		AI_Wait(self,0.5);
		return LOOP_CONTINUE;
	}
	else if(!C_BodyStateContains(hero,BS_CLIMB) && (self.aivar[AIV_ITEMFREQ] == 1))
	{
		hero.wp = Npc_GetNearestWP(hero);
		self.aivar[AIV_ITEMFREQ] = 2;
		AI_StopLookAt(self);
		AI_SetWalkMode(self,NPC_RUN);
		AI_GotoWP(self,hero.wp);
		return LOOP_CONTINUE;
	}
	else if(self.aivar[AIV_ITEMFREQ] == 2)
	{
		if(C_BodyStateContains(hero,BS_CLIMB))
		{
			self.aivar[AIV_ITEMFREQ] = 0;
			return LOOP_CONTINUE;
		}
		else if(Npc_GetDistToNpc(self,hero) > 400)
		{
			self.aivar[AIV_ITEMFREQ] = 1;
			return LOOP_CONTINUE;
		};
		self.aivar[AIV_ITEMFREQ] = 0;
	};
		//*****************************************************************************
		//added by pawbuj
	 if (self.aivar[AIV_ITEMFREQ] == 0)&&(Check_NpcHangState (hero) == true)
	 	{
		//startnpc = Npc_GetNearestWP(self);
		AI_Wait(self,4);
		//hanged  = true;
		Npc_SetStateTime(self,0);
		//PrintScreen (ConcatStrings (self.name,startnpc),-1,-1,"FONT_OLD_10_WHITE.TGA",5);		
		return LOOP_CONTINUE;
		};	
		//added by pawbuj
		//************************************************************************************
	
	if((self.id == 524) && !self.aivar[AIV_PARTYMEMBER])
	{
		return LOOP_END;
	};
	if(C_BodyStateContains(hero,BS_WALK))
	{
		AI_SetWalkMode(self,NPC_WALK);
	}
	else if(!C_BodyStateContains(self,BS_SWIM))
	{
		AI_SetWalkMode(self,NPC_RUN);
	};
	if(Npc_GetDistToNpc(self,hero) > 300)
	{
		AI_GotoNpc(self,hero);
	}
	else if(!C_BodyStateContains(self,BS_CLIMB))
	{
		B_SmartTurnToNpc(self,hero);
	};
	return LOOP_CONTINUE;
};

func void ZS_FollowPC_End()
{
	PrintDebugNpc(PD_TA_FRAME,"ZS_FollowPC_End");
	self.senses = hero.senses;
	self.aivar[AIV_ITEMFREQ] = 0;
};

func void B_FollowPC_AssessSC()
{
	PrintDebugNpc(PD_TA_FRAME,"B_FollowPC_AssessSC");
	if((Npc_GetDistToNpc(self,hero) < 300) && !C_BodyStateContains(self,BS_CLIMB) && !self.aivar[AIV_ITEMFREQ])
	{
		PrintDebugNpc(PD_TA_CHECK,"...SC-Meister jetzt nahe genug!");
		B_FullStop(self);
	};
	if(Npc_CheckInfo(self,1))
	{
		PrintDebugNpc(PD_TA_CHECK,"...wichtige Info zu vergeben!");
		if(!hero.aivar[AIV_INVINCIBLE])
		{
			hero.aivar[AIV_IMPORTANT] = TRUE;
			B_FullStop(other);
			B_FullStop(self);
		};
		AI_StartState(self,ZS_Talk,0,"");
		return;
	};
};

func void B_FollowPC_AssessOthersDamage()
{
	var C_Npc her;
	var C_Npc rock;
		her = Hlp_GetNpc(PC_Hero);
	rock = Hlp_GetNpc(PC_Rockefeller);
	if((Hlp_GetInstanceID(other) == Hlp_GetInstanceID(her)) || (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(rock)))
	{
		if(!Npc_IsInState(self,ZS_Attack))
		{
		var string asysta;
		asysta = ConcatStrings (self.name," rusza z pomocą!");	
		PrintScreen ("O", 3,48,"PAWBUJ2.TGA",3);//GOTHIC		
		PrintScreen		(asysta, 9, 50, _STR_FONT_ONSCREEN, 3 );
		Npc_ClearAIQueue(self);
			Npc_SetTarget(self,victim);
			AI_StartState(self,ZS_Attack,0,"");
		};
	}
	else if((Hlp_GetInstanceID(victim) == Hlp_GetInstanceID(her)) || (Hlp_GetInstanceID(victim) == Hlp_GetInstanceID(rock)))
	{
	
		asysta = ConcatStrings (self.name," rusza z odsieczą!");	
		PrintScreen ("O", 3,48,"PAWBUJ2.TGA",3);//GOTHIC		
		PrintScreen		(asysta, 9, 50, _STR_FONT_ONSCREEN, 3 );
	Npc_ClearAIQueue(self);
	Npc_SetTarget(self,other);
	AI_StartState(self,ZS_Attack,0,"");
	};
};

@pawbuj1981
Copy link

pawbuj1981 commented Mar 20, 2021

I looked in my files and found the int func which is necessary to run previous code, now should be working !
BTW I dont know why the whole code is displayed properly.

func string oCAniCtrl__GetCurrentAniName(var int oCAniCtrl_Ptr)
{
	var int hlp;
	hlp = MEM_ReadInt(oCAniCtrl_Ptr+104);//zCModel 		
	if(hlp) 
	{
		hlp = MEM_ReadInt(hlp+56);//*ActiveAniLayer1			
		if(hlp)
		{
			hlp = MEM_ReadInt(hlp);//*oCAni				
			if(hlp)
			{ 
				return MEM_ReadString(hlp+36); // This will read active ani name(?)
			};//aniname(zstring)
		};
	};
	return "ERROR";
};

func int Check_NpcHangState(var C_NPC npc)
{
	//var int iswalking; var int isstanding;
	var oCNpc _oCNpc;
	_oCNpc = hlp_getnpc(npc);
	//CALL__thiscall (_oCNpc.anictrl,oCAniCtrl_Human_IsWalking_offset);	iswalking = CALL_GetResult();	
	//CALL__thiscall (_oCNpc.anictrl,oCAniCtrl_Human_IsStanding_offset);	isstanding = CALL_GetResult();		

	var string L1Ani;	
	// Get Current Ani
	L1Ani = oCAniCtrl__GetCurrentAniName(_oCNpc.anictrl);
	if (Hlp_StrCmp(L1Ani,"ERROR")) 			{ return false;};
	if (Hlp_StrCmp(L1Ani,"T_HANG_2_STAND")) { return true ;};
	//|| Ani_BodyStateContains(npc,BS_RUN) )
	
	};

@AmProsius
Copy link
Owner Author

AmProsius commented Mar 20, 2021

BTW I dont know why the whole code is displayed properly.

You have to wrap your code in three backticks to create a code block. To enable syntax highlighting, append a d to the opening backticks:

```d
/* Code goes here */
```

I've updated your post accordingly.

@szapp
Copy link
Collaborator

szapp commented Mar 20, 2021

Just checked that issue a minute ago and it does not works properly . ! I have tested on Gothic 1 vanilla with Pc_FighterFM. Again Gothic Mod Fix team had fixed that. I used their code and little change so I will forward solution soon.

Keep in mind, that the issue here specifically refers to NPCs being interrupted while climbing a ladder and always falling down midway, which - given our testing - is successfully fixed here. There are other cases in which the NPC may still drop, but these are not due to issues with following, but when e.g. the NPC is taking damage. See my notes above:

I am not so sure how often it would happen that an NPC that is involved in a fight (or otherwise) climbs a ladder. Until we experience that more specifically I would like to leave it at this issue, because I checked and I don't see any way to make it work in general without possibly breaking a mod.

The NPC may still be running in circles while the player is climbing the ladder, but the issue of the NPCs not being able to use a ladder is sufficiently addressed here already.

Thanks for your scripts. They seem to add a some minor improvements to the behavior of the NPC while following. Mostly to make the NPC wait while the player is climbing a ladder, follow immediately and avoid running in circles at the bottom of the ladder. Nevertheless, that does not address the issue discussed here. That may be part of general pathfinding, which we might address from a different angle.

szapp added a commit that referenced this pull request Apr 20, 2021
AmProsius added a commit that referenced this pull request May 9, 2021
@szapp szapp added impl: hook script func This issue requires hooking script functions. type: session fix The fix for this issues is persistent across a session. labels Feb 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
impl: hook engine func This issue requires hooking engine functions. impl: hook script func This issue requires hooking script functions. type: session fix The fix for this issues is persistent across a session. validation: validated This issue is still present even with Systempack/Union.
Projects
Fix templates
Modify NPC state
v1.0.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants