Skip to content

Virtual functions

inkoalawetrust edited this page Jul 5, 2024 · 5 revisions

All NPCs in the library share a set of common virtual functions. Which allow them to define custom behaviors on a per-class basis. Like for defining custom attack decision code without having to create your own chase function from scratch.

UserVariableDefaults()

Parameters:

  • None

Return type(s):

  • None

Function:

Used to set the actors' default user variable values, for variables that did not have a custom value passed to them in the editor. GZDoom already has a //$UserDefaultValue editor key. However only works for actors spawned by the map. While this function allows for values to also be set for actors spawned by ACS or the console.

Example:

Say your NPC has a User_SpecialAttackChance variable, allowing mappers to define how likely the actor is to do a special attack. The default chance should be 24 out of 255 for every time it attacks. //$UserDefaultValue can set the default value for NPCs placed on the map. But the default value will be kept to 0 for NPCs spawned through ACS, or the console.

	//$UserDefaultValue 24
	Int User_SpecialAttackChance; //How often does the NPC do its' AOE attack ?

This is where UserVariableDefaults() helps:

	Override Void UserVariableDefaults()
	{
		If (User_SpecialAttackChance == 0) User_SpecialAttackChance = 24; //Default AOE chance.
	}

CanAttack()

Parameters:

  • None

Return type(s):

  • True or false.

Function:

Returns whether or not the NPC can currently attack, by default it just checks if the actor has a missile or melee state, is not dead, and is not in a SECF_NOATTACK sector. More or less vanilla behavior.

ShouldAttack()

Parameters:

  • NoStateJump: If true, the actor should not jump to any state even if the function returns true. This needs to manually be obeyed by overrides to this virtual.

Return type(s):

  • Returns true if the actor should attack, and also makes them actually enter the intended attack state if NoStateJump is off.

Function:

This virtual is the attack decision code of KAI NPCs. By default, it is to be used by chase functions to determine what attack the NPC should perform, if any, and make them actually go to that state. Overriding it allows for custom attack decision code on a per-actor basis, without needing to write new chase functions or other hacks.

Default behavior:

By default, this virtual is a mostly direct ZScript rip of A_Chase's attack decision code. So naturally, it behaves the same as well.

OnWander()

Parameters:

  • None

Return type(s):

  • Returns true or false, if it returns false, the rest of KAI_Wander() is not called.

Function:

Allows executing code every time KAI_Wander() is called, or aborting the functions' execution.

GetAttackLocation()

Parameters:

  • None

Return type(s):

  • Returns a Vector3 coordinate to the location at which the NPC is going to attack.

Function:

Used to determine where the NPC is going to attack at.

Default behavior:

If the NPC has a target, it returns their position, otherwise it returns a null vector*.

IsActorHostile()

Note: This is a ClearScope function. So that it can be called from KAI_LOFRaycast as well.

Parameters:

  • Other: The actor to check if it is hostile.

Return type(s):

  • Returns true if Other is hostile, false otherwise

Function:

Checks if the Other actor is an enemy to the calling KAI NPC or not. Can be used to give NPCs different conditions for if another actor is an enemy or not. Like for making an enemy NPC that doesn't always consider other NPCs to not be hostile like IsHostile() does.

Default behavior:

Just calls IsHostile() by default.

HandleNPCGroupEvent()

Parameters:

  • EventType: The event type that affected the group the NPC is in. To get the group event enums, either do KAI_NPCGroup.GRPEVNT_WHATEVER or WhatGroup.GRPEVNT_WHATEVER.
  • Affected: The actor that was affected by the event that struck the group, such as the actor that joined or left the group.
  • WhatGroup: What specific group that the NPC is in was affected by this event ?

Function:

Called when an NPC group that the NPC is in is struck by an event, as long as the group doesn't have the NPCGRP_NOMEMBERALERT flag. Useful for making individual NPCs react to events on their own, like getting mad if a specific group member dies, or saying something when a new member joins.

Default behavior:

Does nothing if the event type is GRPEVNT_NONE, the Affected pointer is null, or the NPC itself is dead. These checks should usually be added as quick checks when you override this function.

		If (EventType == KAI_NPCGroup.GRPEVNT_NONE || !Affected || IsDead(Self))
			Return;

AssessThreatLevel()

Parameters:

  • Other: The actor whose threat level should be assessed.
  • CheckPlayers: Should players be returned as THREAT_UNSTOPPABLE if they have buddha or god mode. Or be automatically returned as THREAT_DANGEROUS otherwise ? Default is true.

Return type(s):

  • Returns a threat level as an enum value.

Function:

Determines how dangerous the Other actor is. For more information, check the AssessThreatLevel() article.

HandleFollowingActor()

Parameters:

  • BasePos: With the default code, this is the fallback position vector to return if no position or actor to follow is found. On its' own, it could be used for whatever else per-actor, such as being a position to offset from.
  • IgnoreDontFollowPlayers: Used to make the actor ignore +DONTFOLLOWPLAYERS if that flag is relevant in the code.

Return type(s):

  • A Vector3 that is the position of where the NPC should follow, in case it isn't necessarily following an actor pointer. But if an actor IS returned, this vector should be that actors' position!
  • A pointer to the actor the function has determined should be followed.

Function:

As the name says, handles determining what actor or position the NPC should follow around.

By default it makes the actor follow nothing if the current order isn't ORDER_FOLLOW. Otherwise if the actor is hostile, it makes them follow the leader of the first group they're in, or fall back to following their master pointer (If any). If the actor is friendly, it will try to follow the player through the first group they're in, and if they're not in any player-led groups, follow their friendplayer. If IgnoringPlayers is on, it will follow a similar group follow logic as for hostile NPCs, check for a non-player master to follow if there's no groups its' in, and then finally fall back to the friendplayer if there's nobody else to follow.

OnOrderChange()

Parameters:

  • NewOrder: The new order that SetNPCOrder() will give to the NPC.
  • All other parameters are the same as in the SetNPCOrder() call that triggered the virtual.

Return type(s):

  • If it returns true, SetNPCOrder() will run, otherwise, it will abort.

Function:

Can be used to pass additional logic to NPCs whenever they have an order given. Such as to react in a certain way if ordered by a commander of a specific class type, or do some special behavior if the function was called from ACS and such.

AfterOrderChange()

Parameters:

  • OldOrder: The previous order that the NPC had before SetNPCOrder() changed it.
  • All other parameters are the same as in the SetNPCOrder() call that triggered the virtual.

Function:

Works like OnOrderChange(), except that it is called after all of SetNPCOrder() is called.

*A vector with a value of (Double.NaN,Double.NaN,Double.NaN), or -2147483647 on each member. Which is returned as an empty Vector3 by IsEmptyVector3.

Clone this wiki locally