80 lines
3.1 KiB
Plaintext
80 lines
3.1 KiB
Plaintext
|
// FOLLOW SCRIPT
|
||
|
// Now normally an NPC when it has to follow a player would have an entry in
|
||
|
// it's heartbeat script, however it'd be inpractical to go thru all of VoC
|
||
|
// and recode the heartbeat scripts to find and follow the master.
|
||
|
//
|
||
|
// This script is triggered on summoning a monster and loops until it dies
|
||
|
// so the monster will follow it's master without any module-wide or on-creature
|
||
|
// heartbeat scripts being utilised. Additionally the monster despite the lack of
|
||
|
// a heartbeat script will even use the more basic player commands
|
||
|
|
||
|
void WalkLoop(object oPlayer)
|
||
|
{
|
||
|
object oMonster = GetHenchman(oPlayer);
|
||
|
int iCommand = GetLastAssociateCommand(oMonster);
|
||
|
object oItem = GetLocalObject(oMonster, "loMyStone");
|
||
|
int iLastCommand = GetLocalInt(oMonster, "liLastCommand");
|
||
|
|
||
|
int iLifeLeft = GetMaxHitPoints(oMonster) - GetCurrentHitPoints(oMonster);
|
||
|
|
||
|
if(GetIsObjectValid(oMonster)){
|
||
|
if (iCommand == ASSOCIATE_COMMAND_ATTACKNEAREST){
|
||
|
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oMonster, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
|
||
|
|
||
|
AssignCommand(oMonster, ActionAttack(oTarget));
|
||
|
}
|
||
|
else if (iCommand == ASSOCIATE_COMMAND_STANDGROUND){
|
||
|
// Do nothing
|
||
|
}
|
||
|
else if (iCommand == ASSOCIATE_COMMAND_LEAVEPARTY){
|
||
|
SetLocalString(oItem, "lsResRef", "");
|
||
|
SetLocalInt(oItem, "liDamage", 0);
|
||
|
RemoveHenchman(oPlayer, oMonster);
|
||
|
|
||
|
SendMessageToPC(oPlayer, "You said I can leave, bye then!");
|
||
|
PlayVoiceChat(VOICE_CHAT_GOODBYE, oMonster);
|
||
|
|
||
|
DelayCommand(2.0, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_1), GetLocation(oMonster)));
|
||
|
DestroyObject(oMonster, 2.1);
|
||
|
}
|
||
|
else {
|
||
|
AssignCommand(oMonster, ActionMoveToObject(oPlayer, TRUE));
|
||
|
}
|
||
|
|
||
|
// If new orders are given, play a random confirmation
|
||
|
if (iLastCommand != iCommand && iCommand != ASSOCIATE_COMMAND_LEAVEPARTY){
|
||
|
int iStyle;
|
||
|
|
||
|
switch (Random(3)){
|
||
|
case 0:
|
||
|
iStyle = VOICE_CHAT_CANDO;
|
||
|
break;
|
||
|
case 1:
|
||
|
iStyle = VOICE_CHAT_GOODIDEA;
|
||
|
break;
|
||
|
case 2:
|
||
|
iStyle = VOICE_CHAT_YES;
|
||
|
break;
|
||
|
}
|
||
|
PlayVoiceChat(iStyle, oMonster);
|
||
|
}
|
||
|
|
||
|
SetLocalInt(oMonster, "liLastCommand", iCommand);
|
||
|
SetLocalInt(oItem, "liDamage", iLifeLeft); // Write creatures hit points to variable now so if they die they can't just be resummoned.
|
||
|
DelayCommand(6.0, WalkLoop(oPlayer)); // Loop it every 6 seconds
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
DelayCommand(2.0, WalkLoop(OBJECT_SELF));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
NOTES:
|
||
|
- Initial Loop MUST be delayed at least 1 second otherwise character won't have
|
||
|
time to be assigned as Henchman causing the GetObjectIsValid command to return
|
||
|
false and in turn prematurly ending the Loop without it even trying to follow
|
||
|
you.
|
||
|
*/
|