2025/07/21 Update
Added PEPS AI. Full compile.
This commit is contained in:
158
_module/nss/nw_ch_ac1.nss
Normal file
158
_module/nss/nw_ch_ac1.nss
Normal file
@@ -0,0 +1,158 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: nw_ch_ac1
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Associate(Summons, Familiar, Companion) OnHeart beat script when out of combat;
|
||||
This will usually fire every 6 seconds (1 game round).
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_module"
|
||||
#include "0i_menus"
|
||||
void ai_ActionFollow(object oCreature, object oTarget)
|
||||
{
|
||||
if(GetLocalInt(OBJECT_SELF, AI_CURRENT_ACTION_MODE) == AI_LAST_ACTION_MOVE)
|
||||
{
|
||||
float fDistance = GetDistanceBetween(oCreature, oTarget);
|
||||
float fFollowDistance = ai_GetFollowDistance(oCreature);
|
||||
if(fDistance > fFollowDistance)
|
||||
{
|
||||
if(fDistance > fFollowDistance * 5.0 &&
|
||||
ai_GetIsInCombat(oCreature)) AssignCommand(oCreature, JumpToObject(oTarget));
|
||||
else
|
||||
{
|
||||
ClearAllActions();
|
||||
ActionMoveToObject(oTarget, TRUE, fFollowDistance);
|
||||
}
|
||||
}
|
||||
DelayCommand(1.0, ai_ActionFollow(oCreature, oTarget));
|
||||
}
|
||||
}
|
||||
void main()
|
||||
{
|
||||
if (GetAILevel(OBJECT_SELF) == AI_LEVEL_VERY_LOW) return;
|
||||
object oCreature = OBJECT_SELF;
|
||||
if(AI_DEBUG) ai_Counter_Start();
|
||||
// We run our OnSpawn in the heartbeat so the creator can use the original
|
||||
// OnSpawn for their own use.
|
||||
ai_OnAssociateSpawn(oCreature);
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_OnAssociateSpawn");
|
||||
if(AI_DEBUG) ai_Debug("nw_ch_ac1", "37", GetName(oCreature) + " Heartbeat." +
|
||||
" MODE_FOLLOW: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_FOLLOW)) +
|
||||
" Action: " + IntToString(GetCurrentAction(oCreature)));
|
||||
if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return;
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_GetIsBusy/ai_Disabled");
|
||||
// If we are an associate and don't have a master then exit.
|
||||
object oMaster = GetMaster(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("nw_ch_ac1", "43", "oMaster: " + GetName(oMaster));
|
||||
if(oMaster == OBJECT_INVALID)
|
||||
{
|
||||
if(ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
ai_DoAssociateCombatRound(oCreature);
|
||||
return;
|
||||
}
|
||||
ai_CheckForCombat(oCreature, FALSE);
|
||||
return;
|
||||
}
|
||||
// ***** Code for Henchman data and menus *****
|
||||
if(ai_GetIsCharacter(oMaster))
|
||||
{
|
||||
string sAssociateType = ai_GetAssociateType(oMaster, oCreature);
|
||||
ai_CheckAssociateData(oMaster, oCreature, sAssociateType);
|
||||
ai_CheckPCStart(oMaster);
|
||||
if(AI_HENCHMAN_WIDGET)
|
||||
{
|
||||
// This keeps widgets from disappearing and reappearing.
|
||||
int nUiToken = NuiFindWindow(oMaster, sAssociateType + AI_WIDGET_NUI);
|
||||
if(nUiToken)
|
||||
{
|
||||
json jData = NuiGetUserData(oMaster, nUiToken);
|
||||
object oAssociate = StringToObject(JsonGetString(JsonArrayGet(jData, 0)));
|
||||
if(oAssociate != oCreature) NuiDestroy(oMaster, nUiToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!ai_GetWidgetButton(oMaster, BTN_WIDGET_OFF, oCreature, sAssociateType))
|
||||
{
|
||||
ai_CreateWidgetNUI(oMaster, oCreature);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, Get Associate data/Build widget");
|
||||
}
|
||||
// If follow mode we do not want the NPC doing anything but follow.
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_FOLLOW))
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_STAND_GROUND))
|
||||
{
|
||||
ai_TryHealing(oCreature, oCreature);
|
||||
return;
|
||||
}
|
||||
if(ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
ai_DoAssociateCombatRound(oCreature);
|
||||
return;
|
||||
}
|
||||
if(ai_CheckForCombat(oCreature, FALSE)) return;
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, ai_CheckForCombat");
|
||||
if(IsInConversation(oCreature)) return;
|
||||
// In command mode we let the player tell us what to do.
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_COMMANDED))
|
||||
{
|
||||
if(ai_TryHealing(oCreature, oCreature)) return;
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat: TryHealing");
|
||||
if(ai_CheckNearbyObjects(oCreature)) return;
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat: CheckNearbyObjects");
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_SCOUT_AHEAD))
|
||||
{
|
||||
ai_ScoutAhead(oCreature);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finally we check to make sure we are following our master.
|
||||
if(GetCurrentAction(oCreature) != ACTION_FOLLOW)
|
||||
{
|
||||
//ai_Debug("nw_ch_ac1", "66", "Follow master: " +
|
||||
// " Stealth: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH)) +
|
||||
// " Search: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH)));
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_STEALTH))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("nw_ch_ac1", "120", "Going into stealth mode!");
|
||||
int nStealth = GetSkillRank(SKILL_HIDE, oCreature);
|
||||
nStealth += GetSkillRank(SKILL_MOVE_SILENTLY, oCreature);
|
||||
if(nStealth / 2 >= ai_GetCharacterLevels(oCreature))
|
||||
{
|
||||
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
|
||||
SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_AGGRESSIVE_SEARCH))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("nw_ch_ac1", "134", "Going into search mode!");
|
||||
SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE);
|
||||
}
|
||||
else SetActionMode(oCreature, ACTION_MODE_DETECT, FALSE);
|
||||
}
|
||||
// Follow master.
|
||||
if(GetDistanceBetween(oCreature, oMaster) > ai_GetFollowDistance(oCreature))
|
||||
{
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_COMMANDED))
|
||||
{
|
||||
object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = oMaster;
|
||||
//ActionForceFollowObject(oTarget, ai_GetFollowDistance(oCreature));
|
||||
//ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oCreature));
|
||||
SetLocalInt(oCreature, AI_CURRENT_ACTION_MODE, AI_LAST_ACTION_MOVE);
|
||||
ai_ActionFollow(oCreature, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(AI_DEBUG) ai_Counter_End(GetName(oCreature) + ": Heartbeat, end");
|
||||
if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT))
|
||||
{
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(1001));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user