2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// actor.cpp: Base class for character AI.
|
|
|
|
|
|
|
|
#include "g_local.h"
|
|
|
|
#include "actor.h"
|
2023-01-29 22:57:04 +01:00
|
|
|
#include "scriptthread.h"
|
2023-01-31 19:28:10 +01:00
|
|
|
#include "scriptclass.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
#include "doors.h"
|
|
|
|
#include "gibs.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "specialfx.h"
|
|
|
|
#include "object.h"
|
|
|
|
#include "scriptslave.h"
|
|
|
|
#include "explosion.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "playerstart.h"
|
|
|
|
#include "characterstate.h"
|
|
|
|
#include "weaputils.h"
|
|
|
|
#include "player.h"
|
2018-08-02 15:12:07 +02:00
|
|
|
#include "bg_local.h"
|
|
|
|
#include "weapturret.h"
|
2018-08-05 17:56:40 +02:00
|
|
|
#include "sentient.h"
|
2023-04-29 21:56:38 +02:00
|
|
|
#include "g_phys.h"
|
|
|
|
#include "debuglines.h"
|
|
|
|
#include "scriptexception.h"
|
2023-06-17 01:24:20 +02:00
|
|
|
#include "parm.h"
|
|
|
|
#include "../qcommon/tiki.h"
|
2023-01-30 00:23:47 +01:00
|
|
|
|
2019-08-18 22:06:49 +02:00
|
|
|
#include <cmath>
|
2018-08-02 15:12:07 +02:00
|
|
|
|
|
|
|
Vector MINS(-15.0,-15.0,0.0);
|
|
|
|
Vector MAXS(15.0,15.0,96.0);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
|
|
|
extern Vector PLAYER_BASE_MIN;
|
|
|
|
extern Vector PLAYER_BASE_MAX;
|
|
|
|
|
|
|
|
bool bEntinfoInit = false;
|
|
|
|
|
2018-08-02 15:12:07 +02:00
|
|
|
cvar_t *g_showinfo;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2018-08-19 08:26:59 +02:00
|
|
|
const char * gAmericanVoices[] = {"a", "c", "h"};
|
|
|
|
const char * gGermanVoices[] = {"a", "c", "d"};
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetGun
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gun",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"s",
|
|
|
|
"specifies the gun to use",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetGun2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gun",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"s",
|
|
|
|
"specifies the gun to use",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetGun
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gun",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the gun to being used",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_WeaponInternal
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"weapon_internal",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"s",
|
|
|
|
"internal use",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_TestAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"testanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_DistToEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"distancetoenemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the distance from the Actor to its enemy",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_MoveTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"moveto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ss",
|
|
|
|
"anim dest",
|
|
|
|
"Specify the location to move to, with animation anim.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_WalkTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"walkto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"dest",
|
|
|
|
"Specify the location to walk to.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_RunTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"runto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"dest",
|
|
|
|
"Specify the location to run to.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_CrouchTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"crouchto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"dest",
|
|
|
|
"Specify the location to crouch to.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_CrawlTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"crawlto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"dest",
|
|
|
|
"Specify the location to crawl to.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AimAt
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"aimat",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"target",
|
|
|
|
"Specify the target to aim at.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Follow
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"follow",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"Specify the entity to follow.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_DeathEmbalm
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"deathembalm",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"preps the dead actor for turning nonsolid gradually over time",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Anim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"anim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play animation.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Anim_Scripted
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"anim_scripted",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play scripted animation.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Anim_Noclip
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"anim_noclip",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play noclip animation.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_Anim_Attached
|
|
|
|
(
|
|
|
|
"anim_attached",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play attached animation.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AnimLoop
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animloop",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Loop animation.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AnimScript
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animscript",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play the animation script",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AnimScript_Scripted
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animscript_scripted",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play the scripted animation script",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AnimScript_Noclip
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animscript_noclip",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play the noclip animation script",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_AnimScript_Attached
|
|
|
|
(
|
|
|
|
"animscript_attached",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Play a noclip animation even when attached",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Reload_mg42
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"reload_mg42",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Reload the mg42 - only used by machinegunner",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Dumb
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"dumb",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Make Actor dumb.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Physics_On
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"physics_on",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"turn physics on.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Physics_Off
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"physics_off",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"turn physics off.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sifs",
|
|
|
|
"anim slot weight flagged",
|
|
|
|
"Set animation slot",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAnimLength
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setanimlength",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"time",
|
|
|
|
"Set the maximum time an animation will play",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_EndActionAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"endactionanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"End any aiming/action animation which is currently playing",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMotionAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setmotionanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"anim",
|
|
|
|
"Set motion animation (handler scripts only)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAimMotionAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setaimmotionanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ss",
|
|
|
|
"anim_crouch anim_stand",
|
|
|
|
"Set aim motion animation (handler scripts only)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetActionAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setactionanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sff",
|
|
|
|
"base_anim lower_limit upper_limit",
|
|
|
|
"Set the base action animation and range that they cover",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_UpperAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"upperanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"anim",
|
|
|
|
"Set the upper body animation",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetUpperAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setupperanim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"anim",
|
|
|
|
"Set the upper body animation - used by animation script only",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetCrossblendTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"blendtime",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the crossblend time to something other than the default, in seconds",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetCrossblendTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"blendtime",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the crossblend time",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPosition
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"position",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The Position the Actor wants to be and should animate towards",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetPosition
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"position",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The Position the Actor wants to be and should animate towards",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetEmotion
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"emotion",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The method of setting the facial expression of the Actor",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAnimFinal
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animfinal",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Whether the animation was succesfully finished",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetWeaponType
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"weapontype",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The Weapon Type of the Actor",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetWeaponGroup
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"weapongroup",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Specifies weapon animation set to use in anim scripts",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Entity_Start
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"entitystart",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Initialize a Actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_LookAt
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"lookat",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"The actor will look at this entity.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_EyesLookAt
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"eyeslookat",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"The actor will look at this entity.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_PointAt
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"pointat",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"The actor will point at this entity.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_TurnTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turnto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"The actor will turn to this entity.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTurnDoneError
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turndoneerror",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"error",
|
|
|
|
"The error amount that turndone will occur for the turnto command.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTurnDoneError2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turndoneerror",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"error",
|
|
|
|
"The error amount that turndone will occur for the turnto command.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTurnDoneError
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turndoneerror",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The error amount that turndone will occur for the turnto command.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_IdleSayAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"idlesay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"animation",
|
|
|
|
"The name of an idle dialog animation to play",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SayAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"say",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"animation",
|
|
|
|
"The name of a dialog animation to play",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSayAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setsay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"animation",
|
|
|
|
"The name of a dialog animation to play - used by animation script only",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_DamagePuff
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"damagepuff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"vv",
|
|
|
|
"position direction",
|
|
|
|
"Spawns a puff of 'blood' smoke at the speficied location in the specified direction.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAngleYawSpeed
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turnspeed",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"speed",
|
|
|
|
"The turn speed of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAngleYawSpeed2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turnspeed",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"speed",
|
|
|
|
"The turn speed of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAngleYawSpeed
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turnspeed",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The turn speed of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAimTarget
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setaimtarget",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ei",
|
|
|
|
"entity bMakeEnemy",
|
|
|
|
"Sets the primary weapon's aim target. if you pass a 1 for p2, the target will become the current enemy...",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_ReadyToFire
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ReadyToFire",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns if ready to fire",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AIOff
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ai_off",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Turns the AI off for this actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AIOn
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ai_on",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Turns the AI on for this actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetSight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the vision distance of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"max_sight_range",
|
|
|
|
"Sets the vision distance of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSight2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"max_sight_range",
|
|
|
|
"Sets the vision distance of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetHearing
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"hearing",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"The hearing radius of the actor",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetHearing
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"hearing",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"The hearing radius of the actor",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetHearing2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"hearing",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"The hearing radius of the actor",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetFov
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fov",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"The fov angle of the actor",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFov
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fov",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"angle",
|
|
|
|
"The fov angle of the actor",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFov2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fov",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"angle",
|
|
|
|
"The fov angle of the actor",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_idle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the idle type of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeIdle2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_idle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the idle type of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTypeIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_idle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the idle type of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeAttack
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_attack",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the attack type of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeAttack2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_attack",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the attack type of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTypeAttack
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_attack",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the attack type of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeDisguise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_disguise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the disguise type of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeDisguise2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_disguise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the disguise type of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTypeDisguise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_disguise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the disguise type of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseLevel
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_level",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"value",
|
|
|
|
"Sets the disguise level of the actor. May be 1 or 2",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseLevel2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_level",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"value",
|
|
|
|
"Sets the disguise level of the actor. May be 1 or 2",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetDisguiseLevel
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_level",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the disguise level of the actor. May be 1 or 2",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the grenade type of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTypeGrenade2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the grenade type of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTypeGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"type_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the grenade type of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPatrolPath
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"patrolpath",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the patrol path for the actor (must have type set to patrol for effect)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPatrolPath2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"patrolpath",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the patrol path for the actor (must have type set to patrol for effect)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetPatrolPath
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"patrolpath",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the name of the patrol path for the actor (must have type set to patrol for effect)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPatrolWaitTrigger
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"waittrigger",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"b",
|
|
|
|
"bool",
|
|
|
|
"If true, patrol guys and running men wait until triggered to move",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPatrolWaitTrigger2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"waittrigger",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"b",
|
|
|
|
"bool",
|
|
|
|
"If true, patrol guys and running men wait until triggered to move",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetPatrolWaitTrigger
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"waittrigger",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"If true, patrol guys and running men wait until triggered to move",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAlarmNode
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmnode",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the alarm node for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAlarmNode2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmnode",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the alarm node for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAlarmNode
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmnode",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the name of the alarm node for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetPreAlarmThread
|
|
|
|
(
|
|
|
|
"prealarmthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetPreAlarmThread2
|
|
|
|
(
|
|
|
|
"prealarmthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the pre alarm thread for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAlarmThread
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the alarm thread for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAlarmThread2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the alarm thread for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAlarmThread
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"alarmthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the name of the alarm thread for the actor (must have type set to alarm for effect)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseAcceptThread
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_accept_thread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the thread for the actor to start when accepting papers",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseAcceptThread2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_accept_thread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"value",
|
|
|
|
"Sets the name of the thread for the actor to start when accepting papers",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetDisguiseAcceptThread
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_accept_thread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the name of the thread for the actor to start when accepting papers",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAccuracy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"accuracy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"value",
|
|
|
|
"Set percent to hit",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAccuracy2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"accuracy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"value",
|
|
|
|
"Set percent to hit",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAccuracy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"accuracy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set percent to hit",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMinDistance
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mindist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the minimum distance the AI tries to keep between itself and the player",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMinDistance2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mindist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the minimum distance the AI tries to keep between itself and the player",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetMinDistance
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mindist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the minimum distance the AI tries to keep between itself and the player",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMaxDistance
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"maxdist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the maximum distance the AI tries to allow between itself and the player",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMaxDistance2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"maxdist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the maximum distance the AI tries to allow between itself and the player",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetMaxDistance
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"maxdist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the maximum distance the AI tries to keep between itself and the player",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"leash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the maximum distance the AI will wander from its leash home",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"leash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the maximum distance the AI will wander from its leash home",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetLeash2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"leash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the maximum distance the AI will wander from its leash home",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetInterval
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"interval",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the distance AI tries to keep between squadmates while moving.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetInterval
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"interval",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the distance AI tries to keep between squadmates while moving.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetInterval2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"interval",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"distance",
|
|
|
|
"Sets the distance AI tries to keep between squadmates while moving.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetRunAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"GetRunAnim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Internal usage",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetWalkAnim
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"GetWalkAnim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Internal usage",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAnimName
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animname",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the animname.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAnimName
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"animname",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Sets the animname.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_range",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"range_in_units",
|
|
|
|
"Sets the maximum distance for disguise behavior to get triggered",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguiseRange2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_range",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"range_in_units",
|
|
|
|
"Sets the maximum distance for disguise behavior to get triggered",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetDisguiseRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_range",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the maximum distance for disguise behavior to get triggered",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguisePeriod
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_period",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"period_in_seconds",
|
|
|
|
"Sets the time between the end of one disguise behavior and start of the next",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDisguisePeriod2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_period",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"period_in_seconds",
|
|
|
|
"Sets the time between the end of one disguise behavior and start of the next",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetDisguisePeriod
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"disguise_period",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the time between the end of one disguise behavior and start of the next",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AttackPlayer
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"attackplayer",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Force Actor to attack the player",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSoundAwareness
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sound_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"awareness_percent",
|
|
|
|
"sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades "
|
|
|
|
"to z"
|
|
|
|
"ero outside sound's radius",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSoundAwareness2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sound_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"awareness_percent",
|
|
|
|
"sets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades "
|
|
|
|
"to z"
|
|
|
|
"ero outside sound's radius",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetSoundAwareness
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"sound_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the awareness of sounds in 0-100 percent chance of hearing a sound withinhalf of the sound's radius' fades "
|
|
|
|
"to z"
|
|
|
|
"ero outside sound's radius",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetGrenadeAwareness
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gren_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"awareness_percent",
|
|
|
|
"sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied "
|
|
|
|
"once e"
|
|
|
|
"very 0.4 seconds)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetGrenadeAwareness2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gren_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"awareness_percent",
|
|
|
|
"sets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied "
|
|
|
|
"once e"
|
|
|
|
"very 0.4 seconds)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetGrenadeAwareness
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"gren_awareness",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the awareness of grenades in 0-100 percent chance of responding to a grenadewhen the AI sees it (applied "
|
|
|
|
"once e"
|
|
|
|
"very 0.4 seconds)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTurret
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turret",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"turret",
|
|
|
|
"Sets the turret of the actor.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetTurret2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turret",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"turret",
|
|
|
|
"Sets the turret of the actor.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetTurret
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"turret",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the turret of the actor.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_AttachGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"attachgrenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Used only by grenade return animations to tell the code when to attach the grenade to the actor",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_DetachGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"detachgrenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Used only by grenade return animations to tell the code when to throw the grenade",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_FireGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fire_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Used only by grenade throw animations to tell the code when to throw a grenade",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_EnableEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enableEnemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"sets enableEnemy variable",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_EnablePain
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enablePain",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"sets enablePain variable",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetPainHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"painhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Sets the current script that will handle pain events",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetPainHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"painhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the current script that will handle pain events",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetDeathHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"deathhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Sets the current script that will handle death events",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetDeathHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"deathhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the current script that will handle death events",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAttackHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"attackhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Sets the current script that will handle attack events",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAttackHandler
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"attackhandler",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the current script that will handle attack events",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAmmoGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ammo_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"grenade_count",
|
|
|
|
"Gives the AI some grenades",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAmmoGrenade2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ammo_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"grenade_count",
|
|
|
|
"Gives the AI some grenades",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAmmoGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"ammo_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns how many grenades an AI has",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMood
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mood",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"new_mood",
|
|
|
|
"sets the AI mood... must be 'bored', 'nervous', 'curious', or 'alert'.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetMood
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mood",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the AI mood: 'bored', 'nervous', 'curious', or 'alert'.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetHeadModel
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"headmodel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"headmodel",
|
|
|
|
"sets the head model",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetHeadModel
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"headmodel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the head model",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetHeadSkin
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"headskin",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"headskin",
|
|
|
|
"sets the head skin",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetHeadSkin
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"headskin",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the head skin",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_ShareEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"share_enemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"internal code use only - shares an AI's enemy with his squad mates.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_ShareGrenade
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"share_grenade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"internal code use only - shares an AI's grenade with his squad mates.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_InterruptPoint
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"interrupt_point",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"hint from animation scripts to AI code that now is a good time to switch animations",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNoIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"no_idle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Specifies if the actor will not go into idle after playing an animation",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetNoIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"no_idle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets if the actor will not go into idle after playing an animation",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the actor's current enemy",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetMaxNoticeTimeScale
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"noticescale",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMaxNoticeTimeScale
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"noticescale",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMaxNoticeTimeScale2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"noticescale",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"Set the max multiplier in time to notice an enemy (default 100, half as big notices twice as fast)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetFixedLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fixedleash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFixedLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fixedleash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFixedLeash2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fixedleash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"if non-zero, the leash will never auto-reset; if zero, the leash may auto-reset",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Holster
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"holster",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"if non-zero, affects offhand",
|
|
|
|
"Holster weapon",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Unholster
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"unholster",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"if non-zero, affects offhand",
|
|
|
|
"Unholster weapon",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_IsEnemyVisible
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"is_enemy_visible",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"0 if the enemy is not currently visible, 1 if he is",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetEnemyVisibleChangeTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enemy_visible_change_time",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the last time whether or not the enemy is visible changed, in seconds",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetLastEnemyVisibleTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"last_enemy_visible_time",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the last time the enemy was visible, in seconds",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFallHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fallheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"height",
|
|
|
|
"Set the fallheight",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFallHeight2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fallheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"height",
|
|
|
|
"Set the fallheight",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetFallHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"fallheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the fallheight",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_CanMoveTo(
|
|
|
|
"canmoveto",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"v",
|
|
|
|
"position",
|
|
|
|
"returns a boolean if the AI can move to a point; for use in anim scripts",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_MoveDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"movedir",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns a unit vector pointing in the current direction of motion, or zero if not moving.This still has meaning "
|
|
|
|
"if v"
|
|
|
|
"elocity is zero but the AI is starting to move on a path.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_ResetLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"resetleash",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"resets the AI's leash to their current position",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_IntervalDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"intervaldir",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"the direction the AI would like to move to maintain its interval",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_Tether
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"tether",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"entity",
|
|
|
|
"the entity to which the AI's leash should be tethered",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetThinkState(
|
|
|
|
"thinkstate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"current ai think state; can be void, idle, pain, killed, attack, curious, disguise, or grenade.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetEnemyShareRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enemysharerange",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the range outside which the AI will not receive notification that a teammate has a new enemy",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetEnemyShareRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enemysharerange",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"range",
|
|
|
|
"sets the range outside which the AI will not receive notification that a teammate has a new enemy",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetEnemyShareRange2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"enemysharerange",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"range",
|
|
|
|
"sets the range outside which the AI will not receive notification that a teammate has a new enemy",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetWeapon
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"weapon",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"weapon_modelname",
|
|
|
|
"Sets the weapon.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetWeapon
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"weapon",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the weapon.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetVoiceType
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"voicetype",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the voice type",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetVoiceType
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"voicetype",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set voicetype to magic letter postfix",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetVoiceType2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"voicetype",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set voicetype to magic letter postfix",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_KickDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"kickdir",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets the direction the AI wants to kick",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetNoLongPain
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nolongpain",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns 1 if long pain is not allowed, or 0 if long pain is allowed.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNoLongPain
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nolongpain",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"allow",
|
|
|
|
"Set to 1 if long pain is not allowed, or 0 if long pain is allowed.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNoLongPain2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nolongpain",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"allow",
|
|
|
|
"Set to 1 if long pain is not allowed, or 0 if long pain is allowed.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetFavoriteEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"favoriteenemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Gets this AI's favorite enemy",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFavoriteEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"favoriteenemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"ai_or_player",
|
|
|
|
"Gets this AI's favorite enemy",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetFavoriteEnemy2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"favoriteenemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"e",
|
|
|
|
"ai_or_player",
|
|
|
|
"Gets this AI's favorite enemy",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetMumble
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mumble",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns 1 if this guy is allowed to mumble, or 0 if he is not",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMumble
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mumble",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"can_mumble",
|
|
|
|
"Set to 1 if this guy is allowed to mumble, or 0 if he is not",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMumble2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"mumble", EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"can_mumble",
|
|
|
|
"Set to 1 if this guy is allowed to mumble, or 0 if he is not",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetBreathSteam
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"breathsteam",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns 1 if this guy is allowed to have steamy breath, or 0 if he is not",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetBreathSteam
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"breathsteam",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"can_breathe_out",
|
|
|
|
"Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetBreathSteam2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"breathsteam",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"can_breathe_out",
|
|
|
|
"Set to 1 if this guy is allowed to have steamy breath, or 0 if he is not",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNextBreathTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nextbreathtime",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"time_in_sec",
|
|
|
|
"Sets the next time the guy will breath out",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_CalcGrenadeToss
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"calcgrenadetoss",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"v",
|
|
|
|
"target_position",
|
|
|
|
"Called to calculate a grenade toss. Must be called before a grenade throwing animation.\n"
|
|
|
|
"Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.\n"
|
|
|
|
"Should be called infrequently, and never during the middle of a grenade toss.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
Event EV_Actor_CalcGrenadeToss2
|
|
|
|
(
|
|
|
|
"calcgrenadetoss2",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"vf",
|
|
|
|
"target_position speed",
|
|
|
|
"Called to calculate a grenade toss. Must be called before a grenade throwing animation.\n"
|
|
|
|
"Returns the name of the script to call with animscript if the toss can succeed, or if the toss won't work.\n"
|
|
|
|
"Should be called infrequently, and never during the middle of a grenade toss.\n"
|
|
|
|
" The speed parameter is optional. Pass a speed if you just want to override and throw no matter what...",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetNoSurprise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nosurprise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets whether or not this guy is allowed to play a surprised animation when first encountering an enemy.\n",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNoSurprise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nosurprise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"nosurprise",
|
|
|
|
"set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetNoSurprise2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"nosurprise",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"nosurprise",
|
|
|
|
"set to 0 to allow this guy to play a surprised animation when first encountering an enemy.\n",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetSilent
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"silent",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets whether or not this guy is allowed to say stuff besides pain and death sounds",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSilent
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"silent",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"silent",
|
|
|
|
"set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetSilent2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"silent",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"silent",
|
|
|
|
"set to 0 to prevent this guy from saying stuff besides pain and death sounds.\n",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetAvoidPlayer
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"avoidplayer",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"is 0 if this AI won't automatically get out of the way, non-zero if he will\n",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAvoidPlayer
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"avoidplayer",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"allowavoid",
|
|
|
|
"set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetAvoidPlayer2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"avoidplayer",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"allowavoid",
|
|
|
|
"set to 0 if this AI shouldn't automatically get out of the way, non-zero if he should.\n",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetMoveDoneRadius
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"movedoneradius",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"Set the waittill movedone radius, default 0 means don't use manual radius",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetMoveDoneRadius
|
|
|
|
(
|
|
|
|
"movedoneradius",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"Set the waittill movedone radius, default 0 means don't use manual radius",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_BeDead
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"bedead",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Forces the actor to be instantly and totally dead; no death animation is played",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetLookAroundAngle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"lookaroundangle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets the angle in degrees left or right of center that the AI will look around while patrolling",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetLookAroundAngle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"lookaroundangle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"angle",
|
|
|
|
"gets the angle in degrees left or right of center that the AI will look around while patrolling",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetLookAroundAngle2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"lookaroundangle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"angle",
|
|
|
|
"gets the angle in degrees left or right of center that the AI will look around while patrolling",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_HasCompleteLookahead
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"hascompletelookahead",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"returns true if there are no corners to turn on the rest of the AI's current path",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_PathDist
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"pathdist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"returns total distance along current path to the path goal",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_CanShootEnemyFrom
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"canshootenemyfrom",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"v",
|
|
|
|
"shootOrigin",
|
|
|
|
"Determines if it would be possible to shoot the sentient's enemy from the given position.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_CanShoot
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"canshoot",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"v",
|
|
|
|
"shootOrigin",
|
|
|
|
"Determines if it would be possible to shoot the sentient's enemy from the given position.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetInReload
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"inreload",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"returns non-zero if the AI is in a reload",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetInReload
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"inreload",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"reloading",
|
|
|
|
"set to non-zero to indicate the AI is in a reload",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetReloadCover
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"setreloadcover",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"do this command to let the ai know it needs to reload; used to reload while going to cover",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_BreakSpecial
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"breakspecial",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"tell ai to break special attack",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetBalconyHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"balconyheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"height",
|
|
|
|
"minimum height a balcony guy must fall to do special balcony death",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_SetBalconyHeight2
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"balconyheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"height",
|
|
|
|
"minimum height a balcony guy must fall to do special balcony death",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
Event EV_Actor_GetBalconyHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
"balconyheight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"minimum height a balcony guy must fall to do special balcony death",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetVisibilityThreshold
|
|
|
|
(
|
|
|
|
"nonvislevel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"visibility level in range 0-1 below which an enemy is treated as non-visible",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetVisibilityThreshold2
|
|
|
|
(
|
|
|
|
"nonvislevel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"visibility level in range 0-1 below which an enemy is treated as non-visible",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetVisibilityThreshold
|
|
|
|
(
|
|
|
|
"nonvislevel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"visibility level in range 0-1 below which an enemy is treated as non-visible",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetDefaultVisibilityThreshold
|
|
|
|
(
|
|
|
|
"defaultnonvislevel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"updates the default value for 'nonvislevel'",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetSuppressChance
|
|
|
|
(
|
|
|
|
"suppresschance",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"sets the percent chance of doing suppressing fire when appropriate (0-100)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetSuppressChance2
|
|
|
|
(
|
|
|
|
"suppresschance",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"sets the percent chance of doing suppressing fire when appropriate (0-100)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetSuppressChance
|
|
|
|
(
|
|
|
|
"suppresschance",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"sets the percent chance of doing suppressing fire when appropriate (0-100)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetIgnoreBadPlace
|
|
|
|
(
|
|
|
|
"ignorebadplaces",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"ignore",
|
|
|
|
"sets whether or not this AI guy will ignore bad places (0 = not suicidal)",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetIgnoreBadPlace2
|
|
|
|
(
|
|
|
|
"ignorebadplaces",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"ignore",
|
|
|
|
"sets whether or not this AI guy will ignore bad places (0 = not suicidal)",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetIgnoreBadPlace
|
|
|
|
(
|
|
|
|
"ignorebadplaces",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"gets whether or not this AI guy will ignore bad places (0 = not suicidal)",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_FindEnemy
|
|
|
|
(
|
|
|
|
"findenemy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Finds the best enemy to target",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
Event EV_Actor_DisableEnemySwitch
|
|
|
|
(
|
|
|
|
"enemyswitchdisable",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Disable enemy switching...",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_EnableEnemySwitch
|
|
|
|
(
|
|
|
|
"enemyswitchenable",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Enable enemy switching...",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetRunAnimRate
|
|
|
|
(
|
|
|
|
"runanimrate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"Set the rate at which the run animation plays back",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetRunAnimRate2
|
|
|
|
(
|
|
|
|
"runanimrate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"multiplier",
|
|
|
|
"Set the rate at which the run animation plays back",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetRunAnimRate
|
|
|
|
(
|
|
|
|
"runanimrate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the rate at which the run animation plays back",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetNationality
|
|
|
|
(
|
|
|
|
"nationality",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"nationality",
|
|
|
|
"Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_SetNationality2
|
|
|
|
(
|
|
|
|
"nationality",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"nationality",
|
|
|
|
"Set the nationality of an actor. Valid entries are default, ger, it, usa, uk, and ussr.",
|
|
|
|
EV_SETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_GetNationality
|
|
|
|
(
|
|
|
|
"nationality",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Get the nationality of an actor. Return values are ger, it, usa, uk, ussr and unset.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
Event EV_Actor_WriteStats
|
|
|
|
(
|
|
|
|
"writestats",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Used internally to write stats to a CSV file.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_CuriousOff
|
|
|
|
(
|
|
|
|
"curiousoff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Turn off an actor's curious state",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
Event EV_Actor_CuriousOn
|
|
|
|
(
|
|
|
|
"curiouson",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Turn on an actor's curious state",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
CLASS_DECLARATION( SimpleActor, Actor, "Actor" )
|
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
{ &EV_Entity_Start, &Actor::EventStart },
|
|
|
|
{ &EV_Actor_MoveTo, &Actor::MoveTo },
|
|
|
|
{ &EV_Actor_WalkTo, &Actor::WalkTo },
|
|
|
|
{ &EV_Actor_RunTo, &Actor::RunTo },
|
|
|
|
{ &EV_Actor_CrouchTo, &Actor::CrouchTo },
|
|
|
|
{ &EV_Actor_CrawlTo, &Actor::CrawlTo },
|
|
|
|
{ &EV_Actor_AimAt, &Actor::AimAt },
|
|
|
|
{ &EV_Pain, &Actor::EventPain },
|
|
|
|
{ &EV_Killed, &Actor::EventKilled },
|
|
|
|
{ &EV_Actor_DeathEmbalm, &Actor::DeathEmbalm },
|
|
|
|
{ &EV_Actor_Anim, &Actor::PlayAnimation },
|
|
|
|
{ &EV_Actor_AnimLoop, &Actor::PlayAnimation },
|
|
|
|
{ &EV_Actor_Anim_Scripted, &Actor::PlayScriptedAnimation },
|
|
|
|
{ &EV_Actor_Anim_Noclip, &Actor::PlayNoclipAnimation },
|
|
|
|
{ &EV_Actor_AnimScript, &Actor::EventAnimScript },
|
|
|
|
{ &EV_Actor_AnimScript_Scripted, &Actor::EventAnimScript_Scripted },
|
|
|
|
{ &EV_Actor_AnimScript_Noclip, &Actor::EventAnimScript_Noclip },
|
|
|
|
{ &EV_Actor_Reload_mg42, &Actor::EventReload_mg42 },
|
|
|
|
{ &EV_Actor_Dumb, &Actor::Dumb },
|
|
|
|
{ &EV_Actor_Physics_On, &Actor::PhysicsOn },
|
|
|
|
{ &EV_Actor_Physics_Off, &Actor::PhysicsOff },
|
|
|
|
{ &EV_Actor_SetAnim, &Actor::EventSetAnim },
|
|
|
|
{ &EV_Actor_SetAnimLength, &SimpleActor::EventSetAnimLength },
|
|
|
|
{ &EV_Actor_EndActionAnim, &Actor::EventEndActionAnim },
|
|
|
|
{ &EV_Actor_SetMotionAnim, &Actor::EventSetMotionAnim },
|
|
|
|
{ &EV_Actor_SetAimMotionAnim, &Actor::EventSetAimMotionAnim },
|
|
|
|
{ &EV_Actor_SetActionAnim, &Actor::EventSetActionAnim },
|
|
|
|
{ &EV_Actor_UpperAnim, &Actor::EventUpperAnim },
|
|
|
|
{ &EV_Actor_SetUpperAnim, &Actor::EventSetUpperAnim },
|
|
|
|
{ &EV_Actor_SetCrossblendTime, &SimpleActor::EventSetCrossblendTime },
|
|
|
|
{ &EV_Actor_GetCrossblendTime, &SimpleActor::EventGetCrossblendTime },
|
|
|
|
{ &EV_Actor_GetPosition, &SimpleActor::EventGetPosition },
|
|
|
|
{ &EV_Actor_SetPosition, &SimpleActor::EventSetPosition },
|
|
|
|
{ &EV_Actor_SetEmotion, &SimpleActor::EventSetEmotion },
|
|
|
|
{ &EV_Actor_SetAnimFinal, &SimpleActor::EventSetAnimFinal },
|
|
|
|
{ &EV_Actor_GetWeaponType, &SimpleActor::EventGetWeaponType },
|
|
|
|
{ &EV_Actor_GetWeaponGroup, &SimpleActor::EventGetWeaponGroup },
|
|
|
|
{ &EV_Actor_LookAt, &Actor::EventLookAt },
|
|
|
|
{ &EV_Actor_EyesLookAt, &Actor::EventEyesLookAt },
|
|
|
|
{ &EV_Actor_PointAt, &Actor::EventPointAt },
|
|
|
|
{ &EV_Actor_TurnTo, &Actor::EventTurnTo },
|
|
|
|
{ &EV_Actor_SetTurnDoneError, &Actor::EventSetTurnDoneError },
|
|
|
|
{ &EV_Actor_SetTurnDoneError2, &Actor::EventSetTurnDoneError },
|
|
|
|
{ &EV_Actor_GetTurnDoneError, &Actor::EventGetTurnDoneError },
|
|
|
|
{ &EV_Actor_IdleSayAnim, &Actor::EventIdleSayAnim },
|
|
|
|
{ &EV_Actor_SayAnim, &Actor::EventSayAnim },
|
|
|
|
{ &EV_Actor_SetSayAnim, &Actor::EventSetSayAnim },
|
|
|
|
{ &EV_Sentient_UseItem, &Actor::EventGiveWeapon },
|
|
|
|
{ &EV_Sentient_GiveWeapon, &Actor::EventGiveWeapon },
|
|
|
|
{ &EV_Actor_SetWeapon, &Actor::EventGiveWeapon },
|
|
|
|
{ &EV_Actor_GetWeapon, &Actor::EventGetWeapon },
|
|
|
|
{ &EV_Actor_SetGun, &Actor::EventGiveWeapon },
|
|
|
|
{ &EV_Actor_SetGun2, &Actor::EventGiveWeapon },
|
|
|
|
{ &EV_Actor_GetGun, &Actor::EventGetWeapon },
|
|
|
|
{ &EV_Actor_WeaponInternal, &Actor::EventGiveWeaponInternal },
|
|
|
|
{ &EV_Actor_DamagePuff, &Actor::EventDamagePuff },
|
|
|
|
{ &EV_Actor_SetAngleYawSpeed, &Actor::EventSetAngleYawSpeed },
|
|
|
|
{ &EV_Actor_SetAngleYawSpeed2, &Actor::EventSetAngleYawSpeed },
|
|
|
|
{ &EV_Actor_GetAngleYawSpeed, &Actor::EventGetAngleYawSpeed },
|
|
|
|
{ &EV_Actor_SetAimTarget, &Actor::EventSetAimTarget },
|
|
|
|
{ &EV_Actor_ReadyToFire, &Actor::ReadyToFire },
|
|
|
|
{ &EV_Actor_AIOn, &SimpleActor::EventAIOn },
|
|
|
|
{ &EV_Actor_AIOff, &SimpleActor::EventAIOff },
|
|
|
|
{ &EV_DeathSinkStart, &Actor::DeathSinkStart },
|
|
|
|
{ &EV_Actor_GetSight, &Actor::EventGetSight },
|
|
|
|
{ &EV_Actor_SetSight, &Actor::EventSetSight },
|
|
|
|
{ &EV_Actor_SetSight2, &Actor::EventSetSight },
|
|
|
|
{ &EV_Actor_GetHearing, &Actor::EventGetHearing },
|
|
|
|
{ &EV_Actor_SetHearing, &Actor::EventSetHearing },
|
|
|
|
{ &EV_Actor_SetHearing2, &Actor::EventSetHearing },
|
|
|
|
{ &EV_Actor_SetFov, &Actor::EventSetFov },
|
|
|
|
{ &EV_Actor_SetFov2, &Actor::EventSetFov },
|
|
|
|
{ &EV_Actor_GetFov, &Actor::EventGetFov },
|
|
|
|
{ &EV_Actor_DistToEnemy, &Actor::EventDistToEnemy },
|
|
|
|
{ &EV_Actor_SetPatrolPath, &Actor::EventSetPatrolPath },
|
|
|
|
{ &EV_Actor_SetPatrolPath2, &Actor::EventSetPatrolPath },
|
|
|
|
{ &EV_Actor_GetPatrolPath, &Actor::EventGetPatrolPath },
|
|
|
|
{ &EV_Actor_SetPatrolWaitTrigger, &Actor::EventSetPatrolWaitTrigger },
|
|
|
|
{ &EV_Actor_SetPatrolWaitTrigger2, &Actor::EventSetPatrolWaitTrigger },
|
|
|
|
{ &EV_Actor_GetPatrolWaitTrigger, &Actor::EventGetPatrolWaitTrigger },
|
|
|
|
{ &EV_Actor_SetAccuracy, &Actor::EventSetAccuracy },
|
|
|
|
{ &EV_Actor_SetAccuracy2, &Actor::EventSetAccuracy },
|
|
|
|
{ &EV_Actor_GetAccuracy, &Actor::EventGetAccuracy },
|
|
|
|
{ &EV_Actor_SetTypeIdle, &Actor::EventSetTypeIdle },
|
|
|
|
{ &EV_Actor_SetTypeIdle2, &Actor::EventSetTypeIdle },
|
|
|
|
{ &EV_Actor_GetTypeIdle, &Actor::EventGetTypeIdle },
|
|
|
|
{ &EV_Actor_SetTypeAttack, &Actor::EventSetTypeAttack },
|
|
|
|
{ &EV_Actor_SetTypeAttack2, &Actor::EventSetTypeAttack },
|
|
|
|
{ &EV_Actor_GetTypeAttack, &Actor::EventGetTypeAttack },
|
|
|
|
{ &EV_Actor_SetTypeDisguise, &Actor::EventSetTypeDisguise },
|
|
|
|
{ &EV_Actor_SetTypeDisguise2, &Actor::EventSetTypeDisguise },
|
|
|
|
{ &EV_Actor_GetTypeDisguise, &Actor::EventGetTypeDisguise },
|
|
|
|
{ &EV_Actor_SetDisguiseLevel, &Actor::EventSetDisguiseLevel },
|
|
|
|
{ &EV_Actor_SetDisguiseLevel2, &Actor::EventSetDisguiseLevel },
|
|
|
|
{ &EV_Actor_GetDisguiseLevel, &Actor::EventGetDisguiseLevel },
|
|
|
|
{ &EV_Actor_SetTypeGrenade, &Actor::EventSetTypeGrenade },
|
|
|
|
{ &EV_Actor_SetTypeGrenade2, &Actor::EventSetTypeGrenade },
|
|
|
|
{ &EV_Actor_GetTypeGrenade, &Actor::EventGetTypeGrenade },
|
|
|
|
{ &EV_Actor_SetMinDistance, &Actor::EventSetMinDistance },
|
|
|
|
{ &EV_Actor_SetMinDistance2, &Actor::EventSetMinDistance },
|
|
|
|
{ &EV_Actor_GetMinDistance, &Actor::EventGetMinDistance },
|
|
|
|
{ &EV_Actor_SetMaxDistance, &Actor::EventSetMaxDistance },
|
|
|
|
{ &EV_Actor_SetMaxDistance2, &Actor::EventSetMaxDistance },
|
|
|
|
{ &EV_Actor_GetMaxDistance, &Actor::EventGetMaxDistance },
|
|
|
|
{ &EV_Actor_GetLeash, &Actor::EventGetLeash },
|
|
|
|
{ &EV_Actor_SetLeash, &Actor::EventSetLeash },
|
|
|
|
{ &EV_Actor_SetLeash2, &Actor::EventSetLeash },
|
|
|
|
{ &EV_Actor_GetInterval, &Actor::EventGetInterval },
|
|
|
|
{ &EV_Actor_SetInterval, &Actor::EventSetInterval },
|
|
|
|
{ &EV_Actor_SetInterval2, &Actor::EventSetInterval },
|
|
|
|
{ &EV_Actor_GetRunAnim, &Actor::EventGetRunAnim },
|
|
|
|
{ &EV_Actor_GetWalkAnim, &Actor::EventGetWalkAnim },
|
|
|
|
{ &EV_Actor_GetAnimName, &Actor::EventGetAnimName },
|
|
|
|
{ &EV_Actor_SetAnimName, &Actor::EventSetAnimName },
|
|
|
|
{ &EV_Actor_SetDisguiseRange, &Actor::EventSetDisguiseRange },
|
|
|
|
{ &EV_Actor_SetDisguiseRange2, &Actor::EventSetDisguiseRange },
|
|
|
|
{ &EV_Actor_GetDisguiseRange, &Actor::EventGetDisguiseRange },
|
|
|
|
{ &EV_Actor_SetDisguisePeriod, &Actor::EventSetDisguisePeriod },
|
|
|
|
{ &EV_Actor_SetDisguisePeriod2, &Actor::EventSetDisguisePeriod },
|
|
|
|
{ &EV_Actor_GetDisguisePeriod, &Actor::EventGetDisguisePeriod },
|
|
|
|
{ &EV_Actor_SetDisguiseAcceptThread, &Actor::EventSetDisguiseAcceptThread },
|
|
|
|
{ &EV_Actor_SetDisguiseAcceptThread2, &Actor::EventSetDisguiseAcceptThread },
|
|
|
|
{ &EV_Actor_GetDisguiseAcceptThread, &Actor::EventGetDisguiseAcceptThread },
|
|
|
|
{ &EV_Actor_AttackPlayer, &Actor::EventAttackPlayer },
|
|
|
|
{ &EV_Actor_SetAlarmNode, &Actor::EventSetAlarmNode },
|
|
|
|
{ &EV_Actor_SetAlarmNode2, &Actor::EventSetAlarmNode },
|
|
|
|
{ &EV_Actor_GetAlarmNode, &Actor::EventGetAlarmNode },
|
|
|
|
{ &EV_Actor_SetAlarmThread, &Actor::EventSetAlarmThread },
|
|
|
|
{ &EV_Actor_SetAlarmThread2, &Actor::EventSetAlarmThread },
|
|
|
|
{ &EV_Actor_GetAlarmThread, &Actor::EventGetAlarmThread },
|
|
|
|
{ &EV_Actor_SetSoundAwareness, &Actor::EventSetSoundAwareness },
|
|
|
|
{ &EV_Actor_SetSoundAwareness2, &Actor::EventSetSoundAwareness },
|
|
|
|
{ &EV_Actor_GetSoundAwareness, &Actor::EventGetSoundAwareness },
|
|
|
|
{ &EV_Actor_SetGrenadeAwareness, &Actor::EventSetGrenadeAwareness },
|
|
|
|
{ &EV_Actor_SetGrenadeAwareness2, &Actor::EventSetGrenadeAwareness },
|
|
|
|
{ &EV_Actor_GetGrenadeAwareness, &Actor::EventGetGrenadeAwareness },
|
|
|
|
{ &EV_Actor_SetTurret, &Actor::EventSetTurret },
|
|
|
|
{ &EV_Actor_SetTurret2, &Actor::EventSetTurret },
|
|
|
|
{ &EV_Actor_GetTurret, &Actor::EventGetTurret },
|
|
|
|
{ &EV_Actor_AttachGrenade, &Actor::Grenade_EventAttach },
|
|
|
|
{ &EV_Actor_DetachGrenade, &Actor::Grenade_EventDetach },
|
|
|
|
{ &EV_Actor_FireGrenade, &Actor::Grenade_EventFire },
|
|
|
|
{ &EV_Actor_EnableEnemy, &Actor::EventEnableEnemy },
|
|
|
|
{ &EV_Actor_EnablePain, &Actor::EventEnablePain },
|
|
|
|
{ &EV_Activate, &Actor::EventActivate },
|
|
|
|
{ &EV_Actor_GetAmmoGrenade, &Actor::EventGetAmmoGrenade },
|
|
|
|
{ &EV_Actor_SetAmmoGrenade, &Actor::EventSetAmmoGrenade },
|
|
|
|
{ &EV_Actor_SetAmmoGrenade2, &Actor::EventSetAmmoGrenade },
|
|
|
|
{ &EV_Actor_GetMood, &Actor::EventGetMood },
|
|
|
|
{ &EV_Actor_SetMood, &Actor::EventSetMood },
|
|
|
|
{ &EV_Actor_ShareEnemy, &Actor::EventShareEnemy },
|
|
|
|
{ &EV_Actor_ShareGrenade, &Actor::EventShareGrenade },
|
|
|
|
{ &EV_Actor_InterruptPoint, &Actor::EventInterruptPoint },
|
|
|
|
{ &EV_Actor_GetPainHandler, &SimpleActor::EventGetPainHandler },
|
|
|
|
{ &EV_Actor_SetPainHandler, &SimpleActor::EventSetPainHandler },
|
|
|
|
{ &EV_Actor_GetDeathHandler, &SimpleActor::EventGetDeathHandler },
|
|
|
|
{ &EV_Actor_SetDeathHandler, &SimpleActor::EventSetDeathHandler },
|
|
|
|
{ &EV_Actor_GetAttackHandler, &SimpleActor::EventGetAttackHandler },
|
|
|
|
{ &EV_Actor_SetAttackHandler, &SimpleActor::EventSetAttackHandler },
|
|
|
|
{ &EV_Actor_SetHeadModel, &Actor::EventSetHeadModel },
|
|
|
|
{ &EV_Actor_GetHeadModel, &Actor::EventGetHeadModel },
|
|
|
|
{ &EV_Actor_SetHeadSkin, &Actor::EventSetHeadSkin },
|
|
|
|
{ &EV_Actor_GetHeadSkin, &Actor::EventGetHeadSkin },
|
|
|
|
{ &EV_Actor_SetNoIdle, &Actor::EventSetNoIdle },
|
|
|
|
{ &EV_Actor_GetNoIdle, &Actor::EventGetNoIdle },
|
|
|
|
{ &EV_Actor_GetEnemy, &Actor::EventGetEnemy },
|
|
|
|
{ &EV_Actor_GetMaxNoticeTimeScale, &Actor::EventGetMaxNoticeTimeScale },
|
|
|
|
{ &EV_Actor_SetMaxNoticeTimeScale, &Actor::EventSetMaxNoticeTimeScale },
|
|
|
|
{ &EV_Actor_SetMaxNoticeTimeScale2, &Actor::EventSetMaxNoticeTimeScale },
|
|
|
|
{ &EV_Actor_GetFixedLeash, &Actor::EventGetFixedLeash },
|
|
|
|
{ &EV_Actor_SetFixedLeash, &Actor::EventSetFixedLeash },
|
|
|
|
{ &EV_Actor_SetFixedLeash2, &Actor::EventSetFixedLeash },
|
|
|
|
{ &EV_Actor_Holster, &Actor::EventHolster },
|
|
|
|
{ &EV_Actor_Unholster, &Actor::EventUnholster },
|
|
|
|
{ &EV_SoundDone, &Actor::EventSoundDone },
|
|
|
|
{ &EV_Sound, &Actor::EventSound },
|
|
|
|
{ &EV_Actor_IsEnemyVisible, &Actor::EventIsEnemyVisible },
|
|
|
|
{ &EV_Actor_GetEnemyVisibleChangeTime, &Actor::EventGetEnemyVisibleChangeTime },
|
|
|
|
{ &EV_Actor_GetLastEnemyVisibleTime, &Actor::EventGetLastEnemyVisibleTime },
|
|
|
|
{ &EV_Actor_SetFallHeight, &Actor::EventSetFallHeight },
|
|
|
|
{ &EV_Actor_GetFallHeight, &Actor::EventGetFallHeight },
|
|
|
|
{ &EV_Actor_CanMoveTo, &Actor::EventCanMoveTo },
|
|
|
|
{ &EV_Actor_MoveDir, &Actor::EventMoveDir },
|
|
|
|
{ &EV_Actor_IntervalDir, &Actor::EventIntervalDir },
|
|
|
|
{ &EV_Actor_ResetLeash, &Actor::EventResetLeash },
|
|
|
|
{ &EV_Actor_Tether, &Actor::EventTether },
|
|
|
|
{ &EV_Actor_GetThinkState, &Actor::EventGetThinkState },
|
|
|
|
{ &EV_Actor_GetEnemyShareRange, &Actor::EventGetEnemyShareRange },
|
|
|
|
{ &EV_Actor_SetEnemyShareRange, &Actor::EventSetEnemyShareRange },
|
|
|
|
{ &EV_Actor_SetEnemyShareRange2, &Actor::EventSetEnemyShareRange },
|
|
|
|
{ &EV_Actor_GetVoiceType, &Actor::GetVoiceType },
|
|
|
|
{ &EV_Actor_SetVoiceType, &Actor::SetVoiceType },
|
|
|
|
{ &EV_Actor_SetVoiceType2, &Actor::SetVoiceType },
|
|
|
|
{ &EV_Remove, &Actor::Remove },
|
|
|
|
{ &EV_Delete, &Actor::Remove },
|
|
|
|
{ &EV_ScriptRemove, &Actor::Remove },
|
|
|
|
{ &EV_Actor_KickDir, &Actor::EventGetKickDir },
|
|
|
|
{ &EV_Actor_GetNoLongPain, &Actor::EventGetNoLongPain },
|
|
|
|
{ &EV_Actor_SetNoLongPain, &Actor::EventSetNoLongPain },
|
|
|
|
{ &EV_Actor_SetNoLongPain2, &Actor::EventSetNoLongPain },
|
|
|
|
{ &EV_Actor_GetFavoriteEnemy, &Actor::EventGetFavoriteEnemy },
|
|
|
|
{ &EV_Actor_SetFavoriteEnemy, &Actor::EventSetFavoriteEnemy },
|
|
|
|
{ &EV_Actor_SetFavoriteEnemy2, &Actor::EventSetFavoriteEnemy },
|
|
|
|
{ &EV_Actor_GetMumble, &Actor::EventGetMumble },
|
|
|
|
{ &EV_Actor_SetMumble, &Actor::EventSetMumble },
|
|
|
|
{ &EV_Actor_SetMumble2, &Actor::EventSetMumble },
|
|
|
|
{ &EV_Actor_GetBreathSteam, &Actor::EventGetBreathSteam },
|
|
|
|
{ &EV_Actor_SetBreathSteam, &Actor::EventSetBreathSteam },
|
|
|
|
{ &EV_Actor_SetBreathSteam2, &Actor::EventSetBreathSteam },
|
|
|
|
{ &EV_Actor_CalcGrenadeToss, &Actor::EventCalcGrenadeToss },
|
|
|
|
{ &EV_Actor_GetNoSurprise, &Actor::EventGetNoSurprise },
|
|
|
|
{ &EV_Actor_SetNoSurprise, &Actor::EventSetNoSurprise },
|
|
|
|
{ &EV_Actor_SetNoSurprise2, &Actor::EventSetNoSurprise },
|
|
|
|
{ &EV_Actor_GetSilent, &Actor::EventGetSilent },
|
|
|
|
{ &EV_Actor_SetSilent, &Actor::EventSetSilent },
|
|
|
|
{ &EV_Actor_SetSilent2, &Actor::EventSetSilent },
|
|
|
|
{ &EV_Actor_GetAvoidPlayer, &Actor::EventGetAvoidPlayer },
|
|
|
|
{ &EV_Actor_SetAvoidPlayer, &Actor::EventSetAvoidPlayer },
|
|
|
|
{ &EV_Actor_SetAvoidPlayer2, &Actor::EventSetAvoidPlayer },
|
|
|
|
{ &EV_Actor_SetMoveDoneRadius, &Actor::EventSetMoveDoneRadius },
|
|
|
|
{ &EV_Actor_BeDead, &Actor::EventBeDead },
|
|
|
|
{ &EV_Actor_GetLookAroundAngle, &Actor::EventGetLookAroundAngle },
|
|
|
|
{ &EV_Actor_SetLookAroundAngle, &Actor::EventSetLookAroundAngle },
|
|
|
|
{ &EV_Actor_SetLookAroundAngle2, &Actor::EventSetLookAroundAngle },
|
|
|
|
{ &EV_Actor_HasCompleteLookahead, &Actor::EventHasCompleteLookahead },
|
|
|
|
{ &EV_Actor_PathDist, &Actor::EventPathDist },
|
|
|
|
{ &EV_Actor_CanShootEnemyFrom, &Actor::EventCanShootEnemyFrom },
|
|
|
|
{ &EV_Actor_CanShoot, &Actor::EventCanShoot },
|
|
|
|
{ &EV_Actor_GetInReload, &Actor::EventGetInReload },
|
|
|
|
{ &EV_Actor_SetInReload, &Actor::EventSetInReload },
|
|
|
|
{ &EV_Actor_SetReloadCover, &Actor::EventSetReloadCover },
|
|
|
|
{ &EV_Actor_BreakSpecial, &Actor::EventBreakSpecial },
|
|
|
|
{ &EV_Actor_SetBalconyHeight, &Actor::EventSetBalconyHeight },
|
|
|
|
{ &EV_Actor_SetBalconyHeight2, &Actor::EventSetBalconyHeight },
|
|
|
|
{ &EV_Actor_GetBalconyHeight, &Actor::EventGetBalconyHeight },
|
|
|
|
{ &EV_CanSee, &Actor::CanSee },
|
|
|
|
{ NULL, NULL }
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2019-06-29 23:43:30 +02:00
|
|
|
Actor::GlobalFuncs_t Actor::GlobalFuncs[NUM_THINKS];
|
|
|
|
const_str Actor::m_csThinkNames[NUM_THINKS] = {
|
2023-10-11 22:49:06 +02:00
|
|
|
STRING_VOID,
|
|
|
|
STRING_TURRET,
|
|
|
|
STRING_COVER,
|
|
|
|
STRING_PATROL,
|
|
|
|
STRING_RUNNER,
|
|
|
|
STRING_PAIN,
|
|
|
|
STRING_KILLED,
|
|
|
|
STRING_MOVETO,
|
|
|
|
STRING_IDLE,
|
|
|
|
STRING_CURIOUS,
|
|
|
|
STRING_DISGUISE_SALUTE,
|
|
|
|
STRING_DISGUISE_SENTRY,
|
|
|
|
STRING_DISGUISE_OFFICER,
|
|
|
|
STRING_DISGUISE_ROVER,
|
|
|
|
STRING_DISGUISE_NONE,
|
|
|
|
STRING_ALARM,
|
|
|
|
STRING_GRENADE,
|
|
|
|
STRING_MACHINEGUNNER,
|
|
|
|
STRING_DOG_IDLE,
|
|
|
|
STRING_DOG_ATTACK,
|
|
|
|
STRING_DOG_CURIOUS,
|
|
|
|
STRING_DOG_GRENADE,
|
|
|
|
STRING_ANIM,
|
|
|
|
STRING_ANIM_CURIOUS,
|
|
|
|
STRING_AIM,
|
|
|
|
STRING_BALCONY_IDLE,
|
|
|
|
STRING_BALCONY_CURIOUS,
|
|
|
|
STRING_BALCONY_ATTACK,
|
|
|
|
STRING_BALCONY_DISGUISE,
|
|
|
|
STRING_BALCONY_GRENADE,
|
|
|
|
STRING_BALCONY_PAIN,
|
|
|
|
STRING_BALCONY_KILLED,
|
|
|
|
STRING_WEAPONLESS,
|
|
|
|
STRING_NOCLIP,
|
|
|
|
STRING_DEAD
|
2018-09-05 16:55:10 +02:00
|
|
|
};
|
2019-06-29 23:43:30 +02:00
|
|
|
const_str Actor::m_csThinkStateNames[ NUM_THINKSTATES ] = {
|
2023-10-11 22:49:06 +02:00
|
|
|
STRING_VOID,
|
|
|
|
STRING_IDLE,
|
|
|
|
STRING_PAIN,
|
|
|
|
STRING_KILLED,
|
|
|
|
STRING_ATTACK,
|
|
|
|
STRING_CURIOUS,
|
|
|
|
STRING_DISGUISE,
|
|
|
|
STRING_GRENADE,
|
|
|
|
STRING_NOCLIP
|
2018-09-05 16:55:10 +02:00
|
|
|
};
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2018-09-05 17:07:40 +02:00
|
|
|
SafePtr< Actor > Actor::mBodyQueue[MAX_BODYQUEUE];
|
|
|
|
int Actor::mCurBody;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::Actor
|
|
|
|
|
|
|
|
Constructor
|
|
|
|
===============
|
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
Actor::Actor()
|
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
entflags |= EF_ACTOR;
|
|
|
|
|
|
|
|
if( LoadingSavegame )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
edict->s.eType = ET_MODELANIM;
|
|
|
|
edict->r.svFlags |= SVF_MONSTER;
|
|
|
|
edict->r.ownerNum = ENTITYNUM_NONE;
|
|
|
|
edict->clipmask = MASK_MONSTERSOLID;
|
|
|
|
setMoveType( MOVETYPE_WALK );
|
|
|
|
mass = 175;
|
|
|
|
flags |= FL_THINK;
|
|
|
|
flags &= ~FL_ANIMATE;
|
|
|
|
setContentsSolid();
|
|
|
|
setSolidType( SOLID_BBOX );
|
|
|
|
m_fFov = 90.0f;
|
|
|
|
takedamage = DAMAGE_AIM;
|
|
|
|
m_fFovDot = cos( 0.5 * m_fFov * M_PI / 180 );
|
|
|
|
m_eAnimMode = 0;
|
|
|
|
Anim_Emotion(EMOTION_NONE);
|
|
|
|
m_bDoPhysics = true;
|
|
|
|
path_failed_time = 0;
|
|
|
|
health = 100;
|
|
|
|
max_health = 100;
|
|
|
|
m_fAngleYawSpeed = 360;
|
|
|
|
m_fHeadMaxTurnSpeed = 520;
|
|
|
|
m_bHeadAnglesAchieved = true;
|
|
|
|
VectorClear( m_vHeadDesiredAngles );
|
|
|
|
m_fLUpperArmTurnSpeed = 360;
|
|
|
|
m_bLUpperArmAnglesAchieved = true;
|
|
|
|
VectorClear( m_vLUpperArmDesiredAngles );
|
|
|
|
m_fTorsoMaxTurnSpeed = 120;
|
|
|
|
m_fTorsoCurrentTurnSpeed = 0;
|
|
|
|
m_bTorsoAnglesAchieved = true;
|
|
|
|
VectorClear( m_vTorsoDesiredAngles );
|
|
|
|
m_pLookEntity = NULL;
|
|
|
|
m_pPointEntity = NULL;
|
|
|
|
m_pTurnEntity = NULL;
|
|
|
|
VectorClear( edict->s.eyeVector );
|
|
|
|
m_bDoAI = true;
|
|
|
|
m_bTurretNoInitialCover = false;
|
|
|
|
m_bThink = false;
|
|
|
|
m_bAutoAvoidPlayer = true;
|
|
|
|
m_fHearing = 2048;
|
|
|
|
m_PainTime = 0;
|
|
|
|
m_fSight = world->m_fAIVisionDistance;
|
|
|
|
m_bNoLongPain = false;
|
|
|
|
hit_obstacle_time = 0;
|
|
|
|
VectorClear2D( obstacle_vel );
|
|
|
|
m_bLockThinkState = false;
|
|
|
|
InitThinkStates();
|
|
|
|
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
|
|
|
m_fMinDistance = 128;
|
|
|
|
m_fMinDistanceSquared = Square(128);
|
|
|
|
m_fMaxDistance = 1024;
|
|
|
|
m_fMaxDistanceSquared = Square(1024);
|
|
|
|
m_fLeash = 512;
|
|
|
|
m_fLeashSquared = Square(512);
|
|
|
|
m_iEyeUpdateTime = level.inttime;
|
|
|
|
if( m_iEyeUpdateTime < 1000 )
|
|
|
|
m_iEyeUpdateTime = 1000;
|
|
|
|
m_iEyeUpdateTime += rand() % 100 + 100;
|
|
|
|
m_vIntervalDir = vec_zero;
|
|
|
|
m_iIntervalDirTime = 0;
|
|
|
|
edict->r.lastNetTime = -10000000;
|
|
|
|
m_iEnemyCheckTime = 0;
|
|
|
|
m_iEnemyChangeTime = 0;
|
|
|
|
m_iEnemyVisibleCheckTime = 0;
|
|
|
|
m_bNewEnemy = false;
|
|
|
|
m_bEnemyIsDisguised = false;
|
|
|
|
m_bEnemyVisible = false;
|
|
|
|
m_iEnemyVisibleChangeTime = 0;
|
|
|
|
m_iLastEnemyVisibleTime = 0;
|
|
|
|
m_iEnemyFovCheckTime = 0;
|
|
|
|
m_iEnemyFovChangeTime = 0;
|
|
|
|
m_bEnemyInFOV = false;
|
|
|
|
m_iIgnoreSoundsMask = 0;
|
|
|
|
m_State = -1;
|
|
|
|
m_iStateTime = 0;
|
|
|
|
m_iGunPositionCheckTime = 0;
|
|
|
|
m_vLastEnemyPos = vec_origin;
|
|
|
|
m_iLastEnemyPosChangeTime = 0;
|
|
|
|
m_vScriptGoal = vec_origin;
|
|
|
|
m_iNextWatchStepTime = 0;
|
|
|
|
m_iCuriousTime = 0;
|
|
|
|
m_iCuriousLevel = 0;
|
|
|
|
SetCuriousAnimHint(0);
|
|
|
|
m_bScriptGoalValid = false;
|
|
|
|
m_bNoSurprise = false;
|
|
|
|
memset( &m_pPotentialCoverNode, 0, sizeof( m_pPotentialCoverNode ) );
|
|
|
|
m_iPotentialCoverCount = 0;
|
|
|
|
m_pCoverNode = NULL;
|
|
|
|
m_csSpecialAttack = STRING_NULL;
|
|
|
|
m_sCurrentPathNodeIndex = -1;
|
|
|
|
m_iDisguiseLevel = 1;
|
|
|
|
m_iNextDisguiseTime = 1;
|
|
|
|
m_iDisguisePeriod = 30000;
|
|
|
|
m_bNeedReload = false;
|
|
|
|
m_bInReload = false;
|
|
|
|
m_bFaceEnemy = true;
|
|
|
|
m_fMaxDisguiseDistSquared = 256 * 256;
|
|
|
|
m_patrolCurrentNode = NULL;
|
|
|
|
m_csPatrolCurrentAnim = STRING_ANIM_RUN_SCR;
|
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
m_bPatrolWaitTrigger = false;
|
|
|
|
m_fInterval = 128;
|
|
|
|
m_aimNode = NULL;
|
|
|
|
m_vHome = vec_origin;
|
|
|
|
m_bFixedLeash = false;
|
|
|
|
m_pTetherEnt = NULL;
|
|
|
|
m_pGrenade = NULL;
|
|
|
|
m_vGrenadePos = vec_origin;
|
|
|
|
m_eGrenadeMode = AI_GREN_TOSS_NONE;
|
|
|
|
m_iFirstGrenadeTime = 0;
|
|
|
|
m_bGrenadeBounced = false;
|
|
|
|
m_vGrenadeVel = vec_zero;
|
|
|
|
m_vKickDir = vec_zero;
|
|
|
|
m_fNoticeTimeScale = 1.0f;
|
|
|
|
m_iCanShootCheckTime = 0;
|
|
|
|
m_csAnimScript = STRING_ANIM_IDLE_SCR;
|
|
|
|
m_fSoundAwareness = 100;
|
|
|
|
m_fGrenadeAwareness = 20;
|
|
|
|
m_fMaxNoticeTimeScale = 1.0f;
|
|
|
|
m_bCanShootEnemy = false;
|
|
|
|
m_bEnableEnemy = true;
|
|
|
|
m_bDesiredEnableEnemy = true;
|
|
|
|
m_bEnablePain = true;
|
|
|
|
m_bAnimScriptSet = false;
|
|
|
|
m_AnimMode = 0;
|
|
|
|
m_csAnimName = STRING_EMPTY;
|
|
|
|
m_csSayAnim = STRING_EMPTY;
|
|
|
|
m_csUpperAnim = STRING_EMPTY;
|
|
|
|
m_fDfwRequestedYaw = 0;
|
|
|
|
m_fDfwDerivedYaw = 0;
|
|
|
|
m_vDfwPos = vec_zero;
|
|
|
|
m_fDfwTime = 0;
|
|
|
|
m_AlarmNode = NULL;
|
|
|
|
m_csHeadSkin = STRING_EMPTY;
|
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
m_csHeadModel = STRING_EMPTY;
|
|
|
|
m_csLoadOut = STRING_EMPTY;
|
|
|
|
m_iRunHomeTime = 0;
|
|
|
|
m_iLookFlags = 0;
|
|
|
|
m_csWeapon = STRING_EMPTY;
|
|
|
|
m_eDontFaceWallMode = 0;
|
|
|
|
m_WallDir = 0;
|
|
|
|
VectorClear2D( m_PrevObstacleNormal );
|
|
|
|
m_bNoIdleAfterAnim = false;
|
|
|
|
m_fMaxShareDistSquared = 0;
|
|
|
|
m_bBreathSteam = false;
|
|
|
|
m_fMoveDoneRadiusSquared = 0;
|
|
|
|
m_bForceAttackPlayer = false;
|
|
|
|
m_iNextLookTime = 0;
|
|
|
|
m_fLookAroundFov = 45;
|
|
|
|
m_bHasDesiredLookDest = false;
|
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
m_iLastFaceDecideTime = 0;
|
|
|
|
m_iOriginTime = -1;
|
|
|
|
m_fTurnDoneError = 0;
|
|
|
|
m_fBalconyHeight = 128;
|
|
|
|
m_bNoPlayerCollision = false;
|
|
|
|
m_pFallPath = NULL;
|
|
|
|
for( int i = 0; i < MAX_ORIGIN_HISTORY; i++ )
|
|
|
|
{
|
|
|
|
VectorClear2D( m_vOriginHistory[ i ] );
|
|
|
|
}
|
|
|
|
m_bAnimating = false;
|
|
|
|
m_iCurrentHistory = 0;
|
|
|
|
m_bDog = false;
|
|
|
|
m_bBecomeRunner = false;
|
|
|
|
mVoiceType = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::~Actor
|
|
|
|
|
|
|
|
Destructor
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Actor::~Actor()
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::setContentsSolid
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::setContentsSolid
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
setContents(CONTENTS_NOBOTCLIP);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EndStates
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
for (int i = 0; i < NUM_THINKLEVELS; i++)
|
|
|
|
{
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]];
|
|
|
|
|
|
|
|
if (func->EndState)
|
|
|
|
(this->*func->EndState)();
|
|
|
|
|
|
|
|
if (m_pAnimThread)
|
|
|
|
{
|
|
|
|
m_pAnimThread->AbortRegistration(STRING_EMPTY, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearStates
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < NUM_THINKSTATES; i++)
|
|
|
|
{
|
|
|
|
SetThink((eThinkState)i, THINK_VOID);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ResolveVoiceType
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
char validVoice[128];
|
|
|
|
|
|
|
|
if (mVoiceType == -1)
|
|
|
|
{
|
|
|
|
int d = 3.0 * 0.99 * random();
|
|
|
|
if (m_Team == TEAM_AMERICAN)
|
|
|
|
{
|
|
|
|
mVoiceType = gAmericanVoices[d][0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mVoiceType = gGermanVoices[d][0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_Team == TEAM_AMERICAN)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 3 ; i++)
|
|
|
|
{
|
|
|
|
if (gAmericanVoices[i][0] == mVoiceType)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
validVoice[0] = '\0';
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
strcat(validVoice, gAmericanVoices[i]);
|
|
|
|
strcat(validVoice, " ");
|
|
|
|
}
|
|
|
|
Com_Printf("ERROR: Bad voice type %c. Valid American voicetypes are: %s\n", mVoiceType, validVoice);
|
|
|
|
mVoiceType = -1;
|
|
|
|
|
|
|
|
int d = 3.0 * 0.99 * random();
|
|
|
|
mVoiceType = gAmericanVoices[d][0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
if (gGermanVoices[i][0] == mVoiceType)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
validVoice[0] = '\0';
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
strcat(validVoice, gGermanVoices[i]);
|
|
|
|
strcat(validVoice, " ");
|
|
|
|
}
|
|
|
|
Com_Printf("ERROR: Bad voice type %c. Valid German voicetypes are: %s\n", mVoiceType, validVoice);
|
|
|
|
mVoiceType = -1;
|
|
|
|
|
|
|
|
int d = 3.0 * 0.99 * random();
|
|
|
|
mVoiceType = gGermanVoices[d][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventStart
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Initialize actor.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventStart
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ResolveVoiceType();
|
|
|
|
setSize(MINS, MAXS);//notsure
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
droptofloor(16384);
|
|
|
|
|
|
|
|
SetControllerTag( HEAD_TAG, gi.Tag_NumForName( edict->tiki, "Bip01 Head" ) );
|
|
|
|
SetControllerTag( TORSO_TAG, gi.Tag_NumForName( edict->tiki, "Bip01" ) );
|
|
|
|
SetControllerTag( ARMS_TAG, gi.Tag_NumForName( edict->tiki, "Bip01 L UpperArm" ) );
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
JoinNearbySquads();
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (level.Spawned())
|
|
|
|
{
|
|
|
|
Unregister(STRING_SPAWN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearEnemies
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_PotentialEnemies.RemoveAll();
|
|
|
|
SetEnemy( NULL, false );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetMoveInfo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Copies current move information to mm.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetMoveInfo
|
|
|
|
(
|
|
|
|
mmove_t *mm
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
memset(mm, 0, sizeof(mmove_t));
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
mm->velocity[0] = velocity.x;
|
|
|
|
mm->velocity[1] = velocity.y;
|
|
|
|
mm->velocity[2] = velocity.z;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
mm->origin[0] = origin.x;
|
|
|
|
mm->origin[1] = origin.y;
|
|
|
|
mm->origin[2] = origin.z;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
mm->entityNum = entnum;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
mm->walking = m_walking;
|
|
|
|
|
|
|
|
mm->groundPlane = m_groundPlane;
|
|
|
|
mm->groundPlaneNormal[0] = m_groundPlaneNormal[0];
|
|
|
|
mm->groundPlaneNormal[1] = m_groundPlaneNormal[1];
|
|
|
|
mm->groundPlaneNormal[2] = m_groundPlaneNormal[2];
|
|
|
|
|
|
|
|
mm->frametime = level.frametime;
|
|
|
|
|
|
|
|
mm->mins[0] = MINS.x;
|
|
|
|
mm->mins[1] = MINS.y;
|
|
|
|
mm->mins[2] = MINS.z;
|
|
|
|
mm->maxs[0] = MAXS.x;
|
|
|
|
mm->maxs[1] = MAXS.y;
|
|
|
|
mm->maxs[2] = MAXS.z;
|
|
|
|
|
|
|
|
mm->tracemask = m_bNoPlayerCollision == false ? MASK_PATHSOLID : MASK_TARGETPATH;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DoFailSafeMove
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DoFailSafeMove
|
|
|
|
(
|
|
|
|
vec3_t dest
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("(entnum %d, radnum %d) blocked, doing failsafe\n", entnum, radnum);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorCopy(dest, m_NoClipDest);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
SetThinkState(THINKSTATE_NOCLIP, THINKLEVEL_NOCLIP);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GetMoveInfo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Fetch current move information from mm.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::GetMoveInfo
|
|
|
|
(
|
|
|
|
mmove_t *mm
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
m_walking = mm->walking;
|
|
|
|
m_groundPlane = mm->groundPlane;
|
|
|
|
m_groundPlaneNormal = mm->groundPlaneNormal;
|
|
|
|
groundentity = NULL;
|
|
|
|
|
|
|
|
TouchStuff(mm);
|
|
|
|
|
|
|
|
if (m_eAnimMode >= 2)
|
|
|
|
{
|
|
|
|
if (m_eAnimMode <= 3)
|
|
|
|
{
|
|
|
|
if (mm->hit_temp_obstacle)
|
|
|
|
{
|
|
|
|
if (mm->hit_temp_obstacle & 1)
|
|
|
|
{
|
|
|
|
m_Path.Clear();
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
|
|
|
|
if (!IsTeamMate(p))
|
|
|
|
{
|
|
|
|
if (!m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
m_bDesiredEnableEnemy = true;
|
|
|
|
m_bEnableEnemy = true;
|
|
|
|
SetLeashHome(origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
BecomeTurretGuy();
|
|
|
|
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, p);
|
|
|
|
m_bForceAttackPlayer = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
velocity = vec_zero;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mm->hit_obstacle)
|
|
|
|
{
|
|
|
|
if (level.inttime >= m_Path.Time() + 1000)
|
|
|
|
{
|
|
|
|
m_Path.ReFindPath(origin, this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!m_Path.NextNode() ||
|
|
|
|
(!(m_Path.NextNode()->bAccurate && m_Path.IsSide())
|
|
|
|
&& m_Path.NextNode() == m_Path.CurrentNode()
|
|
|
|
&& m_Path.CurrentNode() != m_Path.StartNode())
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_Path.Clear();
|
|
|
|
velocity = vec_zero;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Path.CurrentNode() == m_Path.StartNode())
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ BAD FAILSAFE: %.2f %.2f %.2f, '%s'\n",
|
|
|
|
origin[0],
|
|
|
|
origin[1],
|
|
|
|
origin[2],
|
|
|
|
targetname.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
DoFailSafeMove(m_Path.NextNode()->point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (velocity.lengthXYSquared() < -0.69999999 && level.inttime >= m_Path.Time() + 1000)
|
|
|
|
{
|
|
|
|
m_Path.ReFindPath(origin, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_eAnimMode == 4)
|
|
|
|
{
|
|
|
|
if (mm->hit_temp_obstacle)
|
|
|
|
{
|
|
|
|
if (mm->hit_temp_obstacle & 1)
|
|
|
|
{
|
|
|
|
m_Path.Clear();
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
|
|
|
|
if (!IsTeamMate(p))
|
|
|
|
{
|
|
|
|
if (!m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
m_bDesiredEnableEnemy = true;
|
|
|
|
m_bEnableEnemy = true;
|
|
|
|
SetLeashHome(origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
BecomeTurretGuy();
|
|
|
|
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, p);
|
|
|
|
m_bForceAttackPlayer = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mm->hit_obstacle)
|
|
|
|
{
|
|
|
|
Vector end = m_Dest;
|
|
|
|
end.z -= 16384.0;
|
|
|
|
trace_t trace = G_Trace(
|
|
|
|
Vector(m_Dest),
|
|
|
|
Vector(PLAYER_BASE_MIN),
|
|
|
|
Vector(PLAYER_BASE_MAX),
|
|
|
|
Vector(end),
|
|
|
|
NULL,
|
|
|
|
1,
|
|
|
|
qfalse,
|
|
|
|
"Actor::GetMoveInfo");
|
|
|
|
|
|
|
|
DoFailSafeMove(trace.endpos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setOrigin(mm->origin);
|
|
|
|
|
|
|
|
if (VectorLengthSquared(mm->velocity) < 1)
|
|
|
|
{
|
|
|
|
velocity = vec_zero;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
velocity = mm->velocity;
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::TouchStuff
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::TouchStuff
|
|
|
|
(
|
|
|
|
mmove_t *mm
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int i, j;
|
|
|
|
gentity_t *other;
|
|
|
|
Event *event;
|
|
|
|
|
|
|
|
if (getMoveType() != MOVETYPE_NOCLIP)
|
|
|
|
{
|
|
|
|
G_TouchTriggers( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < mm->numtouch; i++)
|
|
|
|
{
|
|
|
|
other = &g_entities[mm->touchents[i]];
|
|
|
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
gentity_t *ge = &g_entities[j];
|
|
|
|
|
|
|
|
if (ge == other)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j != i)
|
|
|
|
{
|
|
|
|
// duplicated
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't bother touching the world
|
|
|
|
if ((!other->entity) || (other->entity == world))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
event = new Event(EV_Touch);
|
|
|
|
event->AddEntity(this);
|
|
|
|
other->entity->ProcessEvent(event);
|
|
|
|
|
|
|
|
event = new Event(EV_Touch);
|
|
|
|
event->AddEntity(other->entity);
|
|
|
|
ProcessEvent(event);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ResetBoneControllers
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Reset Bone Controllers.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ResetBoneControllers
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (edict->s.bone_tag[HEAD_TAG] != -1)
|
|
|
|
{
|
|
|
|
|
|
|
|
SetControllerAngles(HEAD_TAG, vec_zero);
|
|
|
|
}
|
|
|
|
if (edict->s.bone_tag[TORSO_TAG] != -1)
|
|
|
|
{
|
|
|
|
SetControllerAngles(TORSO_TAG, vec_zero);
|
|
|
|
}
|
|
|
|
if (edict->s.bone_tag[ARMS_TAG] != -1)
|
|
|
|
{
|
|
|
|
SetControllerAngles(ARMS_TAG, vec_zero);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateBoneControllers
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update Bone Controllers.
|
|
|
|
Reversed incorrectly, since decompiled output has different behaviour as reversed output.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateBoneControllers
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
|
|
|
|
{
|
|
|
|
int v1; // eax
|
|
|
|
float v2; // fst7
|
|
|
|
float v3; // ebx
|
|
|
|
float v4; // fst7
|
|
|
|
float error; // fst5
|
|
|
|
float v6; // fst3
|
|
|
|
float v7; // ST34_4
|
|
|
|
float torsoYawError; // edx
|
|
|
|
float fErr1; // fst7
|
|
|
|
float v10; // tt
|
|
|
|
float v11; // fst5
|
|
|
|
float v12; // fst7
|
|
|
|
float v13; // fst5
|
|
|
|
float fErr2; // fst3
|
|
|
|
float fAng1; // fst4
|
|
|
|
float fAng2; // fst5
|
|
|
|
float v17; // fst1
|
|
|
|
float fAng3; // fst4
|
|
|
|
float v19; // fst3
|
|
|
|
float fAng3_; // fst5
|
|
|
|
float fFrameTorsoDist; // fst4
|
|
|
|
float fAng4; // fst5
|
|
|
|
float v23; // fst4
|
|
|
|
float fAng5; // fst6
|
|
|
|
float v25; // ST48_4
|
|
|
|
float v26; // ST38_4
|
|
|
|
float fAng6; // fst6
|
|
|
|
float v28; // fst5
|
|
|
|
float v29; // fst4
|
|
|
|
float fAng7; // fst5
|
|
|
|
float fAng8; // fst2
|
|
|
|
float v32; // fst1
|
|
|
|
float fAng9; // fst6
|
|
|
|
float v34; // fst6
|
|
|
|
float v35; // fst3
|
|
|
|
float v36; // fst1
|
|
|
|
float fAng10; // fst5
|
|
|
|
float v38; // fst3
|
|
|
|
float v39; // fst6
|
|
|
|
float v40; // fst3
|
|
|
|
float v41; // fst5
|
|
|
|
float v42; // fst5
|
|
|
|
float v43; // t1
|
|
|
|
float v44; // fst4
|
|
|
|
float v45; // t2
|
|
|
|
float v46; // fst5
|
|
|
|
float v47; // fst7
|
|
|
|
float v48; // fst5
|
|
|
|
float fAng11; // fst5
|
|
|
|
float v50; // fst5
|
|
|
|
float fAng12; // fst5
|
|
|
|
float v52; // t0
|
|
|
|
float v53; // fst5
|
|
|
|
float v54; // fst7
|
|
|
|
float v55; // fst6
|
|
|
|
float fAng13; // fst7
|
|
|
|
float v57; // fst6
|
|
|
|
float v58; // fst7
|
|
|
|
float v59; // fst6
|
|
|
|
float v60; // fst7
|
|
|
|
float v61; // fst6
|
|
|
|
float fAng15; // fst7
|
|
|
|
float v63; // tt
|
|
|
|
float v64; // fst6
|
|
|
|
float v65; // t0
|
|
|
|
float v66; // fst6
|
|
|
|
float v67; // fst2
|
|
|
|
float v68; // tt
|
|
|
|
float v69; // fst4
|
|
|
|
float v70; // t1
|
|
|
|
float v71; // fst4
|
|
|
|
float v72; // t2
|
|
|
|
float v73; // fst4
|
|
|
|
float v74; // tt
|
|
|
|
float v75; // fst4
|
|
|
|
int16_t tagnum; // ax
|
|
|
|
signed int v77; // ebx
|
|
|
|
float v78; // fst7
|
|
|
|
float v79; // fst6
|
|
|
|
float v80; // fst5
|
|
|
|
int *v81; // eax
|
|
|
|
float v82; // fst4
|
|
|
|
float v83; // fst3
|
|
|
|
float v84; // fst4
|
|
|
|
float v85; // t2
|
|
|
|
float v86; // tt
|
|
|
|
float v87; // fst4
|
|
|
|
float v88; // fst5
|
|
|
|
float v89; // fst6
|
|
|
|
float v90; // t0
|
|
|
|
float v91; // eax
|
|
|
|
signed int v92; // edx
|
|
|
|
float *v93; // eax
|
|
|
|
float v94; // fst7
|
|
|
|
float v95; // fst5
|
|
|
|
float v96; // t0
|
|
|
|
float v97; // fst5
|
|
|
|
float v98; // t1
|
|
|
|
float v99; // fst5
|
|
|
|
float v100; // fst6
|
|
|
|
signed int fAlpha; // ebx
|
|
|
|
float fAlpha2; // ST34_4 MAPDST
|
|
|
|
int *v104; // eax
|
|
|
|
signed int v105; // edx
|
|
|
|
float v106; // fst6
|
|
|
|
float v107; // fst5
|
|
|
|
float v108; // fst4
|
|
|
|
float v109; // fst3
|
|
|
|
float v110; // fst7
|
|
|
|
float v111; // fst2
|
|
|
|
float v112; // fst0
|
|
|
|
float v113; // fst1
|
|
|
|
float v114; // fst2
|
|
|
|
float v115; // t1
|
|
|
|
float v116; // fst1
|
|
|
|
float v117; // fst3
|
|
|
|
float v118; // tt
|
|
|
|
float v119; // fst2
|
|
|
|
float v120; // fst5
|
|
|
|
float v121; // t0
|
|
|
|
float v122; // fst2
|
|
|
|
float v123; // fst7
|
|
|
|
float v124; // fst6
|
|
|
|
float v125; // t1
|
|
|
|
float v126; // fst3
|
|
|
|
float v127; // t2
|
|
|
|
float v128; // fst3
|
|
|
|
float v129; // tt
|
|
|
|
int *v130; // eax
|
|
|
|
signed int v131; // edx
|
|
|
|
float v132; // fst6
|
|
|
|
float v133; // fst5
|
|
|
|
float v134; // fst4
|
|
|
|
float v135; // fst3
|
|
|
|
float v136; // fst7
|
|
|
|
float v137; // fst2
|
|
|
|
float v138; // fst0
|
|
|
|
float v139; // fst1
|
|
|
|
float v140; // fst2
|
|
|
|
float v141; // tt
|
|
|
|
float v142; // fst1
|
|
|
|
float v143; // fst3
|
|
|
|
float v144; // t1
|
|
|
|
float v145; // fst2
|
|
|
|
float v146; // fst5
|
|
|
|
float v147; // t2
|
|
|
|
float v148; // fst2
|
|
|
|
float v149; // fst7
|
|
|
|
float v150; // fst6
|
|
|
|
float v151; // tt
|
|
|
|
float v152; // fst3
|
|
|
|
float v153; // t0
|
|
|
|
float v154; // fst3
|
|
|
|
float v155; // t1
|
|
|
|
signed int v156; // ebx
|
|
|
|
float v157; // fst7
|
|
|
|
float v158; // fst6
|
|
|
|
float v159; // fst5
|
|
|
|
int *v160; // eax
|
|
|
|
float v161; // fst4
|
|
|
|
float v162; // fst3
|
|
|
|
float v163; // fst4
|
|
|
|
float v164; // t1
|
|
|
|
float v165; // t2
|
|
|
|
float v166; // fst4
|
|
|
|
float v167; // fst5
|
|
|
|
float v168; // fst6
|
|
|
|
float v169; // tt
|
|
|
|
SimpleEntityPtr v170; // ecx
|
|
|
|
struct gentity_s *v171; // esi
|
|
|
|
float v172; // [esp+2Ch] [ebp-20Ch]
|
|
|
|
float v173; // [esp+2Ch] [ebp-20Ch]
|
|
|
|
float v174; // [esp+7Ch] [ebp-1BCh]
|
|
|
|
float v175; // [esp+80h] [ebp-1B8h]
|
|
|
|
float v176; // [esp+84h] [ebp-1B4h]
|
|
|
|
Vector v177; // [esp+90h] [ebp-1A8h]
|
|
|
|
Vector v178; // [esp+A0h] [ebp-198h]
|
|
|
|
float v179; // [esp+B0h] [ebp-188h]
|
|
|
|
float v180; // [esp+B4h] [ebp-184h]
|
|
|
|
float v181; // [esp+B8h] [ebp-180h]
|
|
|
|
float v182[3]; // [esp+C0h] [ebp-178h]
|
|
|
|
float fDist; // [esp+DCh] [ebp-15Ch]
|
|
|
|
float v184; // [esp+E0h] [ebp-158h]
|
|
|
|
float v185; // [esp+E4h] [ebp-154h]
|
|
|
|
float v186; // [esp+E8h] [ebp-150h]
|
|
|
|
float v187[3]; // [esp+F0h] [ebp-148h]
|
|
|
|
float v188; // [esp+100h] [ebp-138h]
|
|
|
|
float v189; // [esp+104h] [ebp-134h]
|
|
|
|
float v190; // [esp+108h] [ebp-130h]
|
|
|
|
float vLookDest[3]; // [esp+110h] [ebp-128h]
|
|
|
|
orientation_t tag_or; // [esp+120h] [ebp-118h]
|
|
|
|
float v193[3]; // [esp+150h] [ebp-E8h]
|
|
|
|
float v194[4]; // [esp+160h] [ebp-D8h]
|
|
|
|
float v195[3]; // [esp+170h] [ebp-C8h]
|
|
|
|
float lookAxis[3][3]; // [esp+180h] [ebp-B8h]
|
|
|
|
float v197[3]; // [esp+1B0h] [ebp-88h]
|
|
|
|
float myAxis[3][3]; // [esp+1C0h] [ebp-78h]
|
|
|
|
float LocalLookAngles[3]; // [esp+1F0h] [ebp-48h]
|
|
|
|
float torsoAngles[3]; // [esp+200h] [ebp-38h]
|
|
|
|
float headAngles[3]; // [esp+210h] [ebp-28h]
|
|
|
|
int v202; // [esp+220h] [ebp-18h]
|
|
|
|
|
|
|
|
torsoAngles[2] = 0.0;
|
|
|
|
headAngles[0] = 0.0;
|
|
|
|
headAngles[1] = 0.0;
|
|
|
|
headAngles[2] = 0.0;
|
|
|
|
torsoAngles[0] = 0.0;
|
|
|
|
torsoAngles[1] = 0.0;
|
|
|
|
if (m_bHasDesiredLookAngles)
|
|
|
|
{
|
|
|
|
v1 = g_showlookat->integer;
|
|
|
|
if (v1 != entnum && v1 != -1)
|
|
|
|
{
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_4:
|
|
|
|
v2 = m_DesiredLookAngles[0];
|
|
|
|
LocalLookAngles[0] = m_DesiredLookAngles[0];
|
|
|
|
LocalLookAngles[1] = m_DesiredLookAngles[1];
|
|
|
|
v3 = m_DesiredLookAngles[2];
|
|
|
|
v178[0] = 0.0;
|
|
|
|
LocalLookAngles[2] = v3;
|
|
|
|
v177[2] = v3;
|
|
|
|
v178[1] = 0.0;
|
|
|
|
v178[2] = 0.0;
|
|
|
|
v177[0] = v2;
|
|
|
|
v177[1] = LocalLookAngles[1];
|
|
|
|
v177.AngleVectorsLeft(&v178);
|
|
|
|
edict->s.eyeVector[0] = v178[0];
|
|
|
|
edict->s.eyeVector[1] = v178[1];
|
|
|
|
edict->s.eyeVector[2] = v178[2];
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_5;
|
|
|
|
}
|
|
|
|
tagnum = gi.Tag_NumForName(edict->tiki, "eyes bone");
|
|
|
|
v77 = 0;
|
|
|
|
tag_or = G_TIKI_Orientation(edict, tagnum & 0x3FF);
|
|
|
|
AnglesToAxis(angles, myAxis);
|
|
|
|
v197[0] = origin[0];
|
|
|
|
v197[1] = origin[1];
|
|
|
|
v78 = v197[0];
|
|
|
|
v79 = v197[1];
|
|
|
|
v80 = origin[2];
|
|
|
|
v197[2] = origin[2];
|
|
|
|
v81 = &v202;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
v82 = tag_or.origin[v77++];
|
|
|
|
v78 = v78 + *(v81 - 24) * v82;
|
|
|
|
v83 = v82;
|
|
|
|
v84 = *(v81 - 23) * v82;
|
|
|
|
v85 = v83 * *(v81 - 22);
|
|
|
|
v81 += 3;
|
|
|
|
v86 = v84 + v79;
|
|
|
|
v87 = v80;
|
|
|
|
v88 = v86;
|
|
|
|
v89 = v85 + v87;
|
|
|
|
if (v77 > 2)
|
|
|
|
break;
|
|
|
|
v90 = v88;
|
|
|
|
v80 = v89;
|
|
|
|
v79 = v90;
|
|
|
|
}
|
|
|
|
v197[2] = v89;
|
|
|
|
v197[1] = v88;
|
|
|
|
v197[0] = v78;
|
|
|
|
vLookDest[0] = 0.0;
|
|
|
|
vLookDest[1] = 0.0;
|
|
|
|
vLookDest[2] = 0.0;
|
|
|
|
if (m_bHasDesiredLookDest)
|
|
|
|
{
|
|
|
|
v188 = m_vDesiredLookDest[0];
|
|
|
|
v189 = m_vDesiredLookDest[1];
|
|
|
|
v91 = m_vDesiredLookDest[2];
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_105:
|
|
|
|
v190 = v91;
|
|
|
|
vLookDest[0] = v188;
|
|
|
|
vLookDest[2] = v91;
|
|
|
|
vLookDest[1] = v189;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_106;
|
|
|
|
}
|
|
|
|
v170 = this->m_pLookEntity;
|
|
|
|
if (v170)
|
|
|
|
{
|
|
|
|
if (!v170->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
v188 = v170->centroid[0];
|
|
|
|
v189 = v170->centroid[1];
|
|
|
|
v91 = v170->centroid[2];
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_105;
|
|
|
|
}
|
|
|
|
((Sentient *)v170.Pointer())->EyePosition().copyTo(vLookDest);
|
|
|
|
}
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_106:
|
|
|
|
v92 = 0;
|
|
|
|
v93 = angles;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
v94 = *v93;
|
|
|
|
++v93;
|
|
|
|
v194[v92] = v94 + m_DesiredLookAngles[v92];
|
|
|
|
++v92;
|
|
|
|
} while (v92 <= 2);
|
|
|
|
AnglesToAxis(v194, lookAxis);
|
|
|
|
v188 = vLookDest[0] - v197[0];
|
|
|
|
v189 = vLookDest[1] - v197[1];
|
|
|
|
v190 = vLookDest[2] - v197[2];
|
|
|
|
VectorNormalize(&v188);
|
|
|
|
v187[0] = v188;
|
|
|
|
v187[1] = v189;
|
|
|
|
v187[2] = v190;
|
|
|
|
v95 = v188 - lookAxis[0][0];
|
|
|
|
v184 = v95;
|
|
|
|
v96 = v95 * v95;
|
|
|
|
v97 = v189 - lookAxis[0][1];
|
|
|
|
v185 = v97;
|
|
|
|
v98 = v97 * v97;
|
|
|
|
v99 = v190 - lookAxis[0][2];
|
|
|
|
v186 = v99;
|
|
|
|
v100 = v99 * v99 + v98 + v96;
|
|
|
|
fDist = sqrt(v100);
|
|
|
|
if (fDist >= 0.1)
|
|
|
|
{
|
|
|
|
v193[0] = 128.0;
|
|
|
|
v156 = 0;
|
|
|
|
v193[1] = 0.0;
|
|
|
|
v157 = v197[0];
|
|
|
|
v158 = v197[1];
|
|
|
|
v159 = v197[2];
|
|
|
|
v195[1] = v197[1];
|
|
|
|
v160 = &v202;
|
|
|
|
v193[2] = 0.0;
|
|
|
|
v195[0] = v197[0];
|
|
|
|
v195[2] = v197[2];
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
v161 = v193[v156++];
|
|
|
|
v157 = v157 + *(v160 - 40) * v161;
|
|
|
|
v162 = v161;
|
|
|
|
v163 = *(v160 - 39) * v161;
|
|
|
|
v164 = v162 * *(v160 - 38);
|
|
|
|
v160 += 3;
|
|
|
|
v165 = v163 + v158;
|
|
|
|
v166 = v159;
|
|
|
|
v167 = v165;
|
|
|
|
v168 = v164 + v166;
|
|
|
|
if (v156 > 2)
|
|
|
|
break;
|
|
|
|
v169 = v167;
|
|
|
|
v159 = v168;
|
|
|
|
v158 = v169;
|
|
|
|
}
|
|
|
|
v195[2] = v168;
|
|
|
|
v195[1] = v167;
|
|
|
|
v195[0] = v157;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v195[0] = vLookDest[0];
|
|
|
|
v195[1] = vLookDest[1];
|
|
|
|
v195[2] = vLookDest[2];
|
|
|
|
fDist = sqrt(v100);
|
|
|
|
if (fDist >= 0.039999999)
|
|
|
|
{
|
|
|
|
fDist = sqrt(v184 * v184 + v185 * v185 + v186 * v186);
|
|
|
|
fAlpha = ((0.1 - fDist) / 0.060000002);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAlpha = 1;
|
|
|
|
}
|
|
|
|
v187[0] = vLookDest[0] + 8.0;
|
|
|
|
v182[0] = vLookDest[0] + 8.0;
|
|
|
|
v187[1] = vLookDest[1] + 8.0;
|
|
|
|
v187[2] = vLookDest[2] + -8.0;
|
|
|
|
fAlpha2 = fAlpha;
|
|
|
|
v182[1] = vLookDest[1] + 8.0;
|
|
|
|
v182[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v182, v187, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + 8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = -8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + -8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + 8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = -8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + -8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = -8.0;
|
|
|
|
v182[1] = -8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + -8.0;
|
|
|
|
v178[1] = vLookDest[1] + -8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + 8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + 8.0;
|
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + 8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = -8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + -8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + 8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
|
|
|
v182[0] = -8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + -8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = -8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = -8.0;
|
|
|
|
v178[0] = vLookDest[0] + -8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + -8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + 8.0;
|
|
|
|
v177[2] = vLookDest[2] + 8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = 8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + 8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = 8.0;
|
|
|
|
v182[2] = -8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + 8.0;
|
|
|
|
v178[2] = vLookDest[2] + -8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + 8.0;
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = -8.0;
|
|
|
|
v182[2] = 8.0;
|
|
|
|
v178[0] = vLookDest[0] + 8.0;
|
|
|
|
v178[1] = vLookDest[1] + -8.0;
|
|
|
|
v178[2] = vLookDest[2] + 8.0;
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
v187[1] = vLookDest[1];
|
|
|
|
v177[0] = vLookDest[0] + -8.0;
|
|
|
|
v187[0] = vLookDest[0];
|
|
|
|
v187[2] = vLookDest[2];
|
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
|
|
|
v182[0] = 8.0;
|
|
|
|
v182[1] = -8.0;
|
|
|
|
v182[2] = -8.0;
|
|
|
|
v177[1] = vLookDest[1] + -8.0;
|
|
|
|
v177[2] = vLookDest[2] + -8.0;
|
|
|
|
v178[0] = 8.0 + vLookDest[0];
|
|
|
|
v178[1] = vLookDest[1] + -8.0;
|
|
|
|
v178[2] = -8.0 + vLookDest[2];
|
|
|
|
G_DebugLine(v178, v177, 0.0, 0.0, fAlpha2, fAlpha2);
|
|
|
|
}
|
|
|
|
G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0);
|
|
|
|
v104 = &v202;
|
|
|
|
v105 = 0;
|
|
|
|
v106 = v197[1];
|
|
|
|
v107 = v197[2];
|
|
|
|
v108 = v195[0];
|
|
|
|
v109 = v195[1];
|
|
|
|
v110 = v195[2];
|
|
|
|
v193[0] = 0.0;
|
|
|
|
v193[1] = 0.0;
|
|
|
|
v193[2] = -2.0;
|
|
|
|
v174 = v197[0];
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
v111 = v193[v105++];
|
|
|
|
v112 = *(v104 - 40) * v111;
|
|
|
|
v108 = v108 + v112;
|
|
|
|
v174 = v174 + v112;
|
|
|
|
v113 = v111;
|
|
|
|
v114 = *(v104 - 39) * v111;
|
|
|
|
v115 = v113 * *(v104 - 38);
|
|
|
|
v104 += 3;
|
|
|
|
v116 = v109;
|
|
|
|
v117 = v106 + v114;
|
|
|
|
v118 = v114 + v116;
|
|
|
|
v119 = v107;
|
|
|
|
v120 = v118;
|
|
|
|
v121 = v119 + v115;
|
|
|
|
v122 = v110;
|
|
|
|
v123 = v121;
|
|
|
|
v124 = v115 + v122;
|
|
|
|
if (v105 > 2)
|
|
|
|
break;
|
|
|
|
v125 = v117;
|
|
|
|
v126 = v124;
|
|
|
|
v106 = v125;
|
|
|
|
v127 = v126;
|
|
|
|
v128 = v123;
|
|
|
|
v110 = v127;
|
|
|
|
v129 = v128;
|
|
|
|
v109 = v120;
|
|
|
|
v107 = v129;
|
|
|
|
}
|
|
|
|
v195[2] = v124;
|
|
|
|
v195[1] = v120;
|
|
|
|
v195[0] = v108;
|
|
|
|
v197[2] = v123;
|
|
|
|
v197[1] = v117;
|
|
|
|
v197[0] = v174;
|
|
|
|
G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0);
|
|
|
|
v130 = &v202;
|
|
|
|
v131 = 0;
|
|
|
|
v132 = v197[1];
|
|
|
|
v133 = v197[2];
|
|
|
|
v134 = v195[0];
|
|
|
|
v135 = v195[1];
|
|
|
|
v136 = v195[2];
|
|
|
|
v193[0] = 0.0;
|
|
|
|
v193[1] = 2.0;
|
|
|
|
v193[2] = 0.0;
|
|
|
|
v175 = v197[0];
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
v137 = v193[v131++];
|
|
|
|
v138 = *(v130 - 40) * v137;
|
|
|
|
v134 = v134 + v138;
|
|
|
|
v175 = v175 + v138;
|
|
|
|
v139 = v137;
|
|
|
|
v140 = *(v130 - 39) * v137;
|
|
|
|
v141 = v139 * *(v130 - 38);
|
|
|
|
v130 += 3;
|
|
|
|
v142 = v135;
|
|
|
|
v143 = v132 + v140;
|
|
|
|
v144 = v140 + v142;
|
|
|
|
v145 = v133;
|
|
|
|
v146 = v144;
|
|
|
|
v147 = v145 + v141;
|
|
|
|
v148 = v136;
|
|
|
|
v149 = v147;
|
|
|
|
v150 = v141 + v148;
|
|
|
|
if (v131 > 2)
|
|
|
|
break;
|
|
|
|
v151 = v143;
|
|
|
|
v152 = v150;
|
|
|
|
v132 = v151;
|
|
|
|
v153 = v152;
|
|
|
|
v154 = v149;
|
|
|
|
v136 = v153;
|
|
|
|
v155 = v154;
|
|
|
|
v135 = v146;
|
|
|
|
v133 = v155;
|
|
|
|
}
|
|
|
|
v195[2] = v150;
|
|
|
|
v195[1] = v146;
|
|
|
|
v195[0] = v134;
|
|
|
|
v197[2] = v149;
|
|
|
|
v197[1] = v143;
|
|
|
|
v197[0] = v175;
|
|
|
|
G_DebugLine(v197, v195, 0.0, 0.0, 1.0, 1.0);
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_4;
|
|
|
|
}
|
|
|
|
v171 = edict;
|
|
|
|
v171->s.eyeVector[2] = 0.0;
|
|
|
|
v171->s.eyeVector[1] = 0.0;
|
|
|
|
v171->s.eyeVector[0] = 0.0;
|
|
|
|
LocalLookAngles[2] = 0.0;
|
|
|
|
LocalLookAngles[1] = 0.0;
|
|
|
|
LocalLookAngles[0] = 0.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_5:
|
|
|
|
GetControllerAngles(1).copyTo(v177);
|
|
|
|
torsoAngles[2] = v177[2];
|
|
|
|
torsoAngles[0] = v177[0];
|
|
|
|
torsoAngles[1] = v177[1];
|
|
|
|
GetControllerAngles(0).copyTo(v177);
|
|
|
|
v4 = LocalLookAngles[0];
|
|
|
|
headAngles[2] = v177[2];
|
|
|
|
headAngles[1] = v177[1];
|
|
|
|
headAngles[0] = v177[0];
|
|
|
|
error = LocalLookAngles[1] - (torsoAngles[1] + v177[1]);
|
|
|
|
v6 = LocalLookAngles[1] - torsoAngles[1];
|
|
|
|
v176 = LocalLookAngles[0] - v177[0];
|
|
|
|
v7 = v6;
|
|
|
|
torsoYawError = v7;
|
|
|
|
if (v6 > 180.0)
|
|
|
|
{
|
|
|
|
v172 = v6 - 360.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_7:
|
|
|
|
torsoYawError = v172;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_8;
|
|
|
|
}
|
|
|
|
if (v6 < -180.0)
|
|
|
|
{
|
|
|
|
v172 = v6 + 360.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_7;
|
|
|
|
}
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_8:
|
|
|
|
if (torsoYawError >= 0.0)
|
|
|
|
{
|
|
|
|
if (error < -120.0)
|
|
|
|
error = error + 360.0;
|
|
|
|
}
|
|
|
|
else if (error > 120.0)
|
|
|
|
{
|
|
|
|
error = error - 360.0;
|
|
|
|
}
|
|
|
|
if (!((((uint8_t)this->m_iLookFlags) ^ 1) & 1))
|
|
|
|
{
|
|
|
|
fAng6 = error;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_25;
|
|
|
|
}
|
|
|
|
if (error <= 25.0)
|
|
|
|
{
|
|
|
|
if (-25.0 <= error)
|
|
|
|
{
|
|
|
|
v12 = error;
|
|
|
|
v13 = 0.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_15;
|
|
|
|
}
|
|
|
|
fErr1 = 0.2 * (error + 25.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fErr1 = (error - 25.0) * 0.2;
|
|
|
|
}
|
|
|
|
v10 = error;
|
|
|
|
v11 = fErr1;
|
|
|
|
v12 = v10;
|
|
|
|
fDist = v11;
|
|
|
|
v13 = fDist;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_15:
|
|
|
|
fErr2 = v12 + headAngles[1];
|
|
|
|
fAng1 = -torsoAngles[1];
|
|
|
|
v173 = fErr2;
|
|
|
|
if (fErr2 > fAng1)
|
|
|
|
{
|
|
|
|
fErr2 = fAng1;
|
|
|
|
fAng1 = v173;
|
|
|
|
}
|
|
|
|
if (fErr2 <= v13)
|
|
|
|
{
|
|
|
|
v74 = fAng1;
|
|
|
|
v75 = v13;
|
|
|
|
fAng2 = v74;
|
|
|
|
if (v75 <= v74)
|
|
|
|
fAng2 = v75;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng2 = fErr2;
|
|
|
|
}
|
|
|
|
v17 = level.frametime * 15.0;
|
|
|
|
fAng3 = this->m_fTorsoCurrentTurnSpeed + v17;
|
|
|
|
v19 = this->m_fTorsoCurrentTurnSpeed - v17;
|
|
|
|
if (fAng2 <= fAng3)
|
|
|
|
{
|
|
|
|
fAng3 = fAng2;
|
|
|
|
if (v19 > fAng2)
|
|
|
|
fAng3 = v19;
|
|
|
|
}
|
|
|
|
fAng3_ = fAng3;
|
|
|
|
fFrameTorsoDist = level.frametime * this->m_fTorsoMaxTurnSpeed;
|
|
|
|
if (-fFrameTorsoDist <= fAng3_)
|
|
|
|
{
|
|
|
|
v72 = fFrameTorsoDist;
|
|
|
|
v73 = fAng3_;
|
|
|
|
fAng4 = v72;
|
|
|
|
if (v73 <= v72)
|
|
|
|
fAng4 = v73;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng4 = -fFrameTorsoDist;
|
|
|
|
}
|
|
|
|
v23 = torsoAngles[1] + fAng4;
|
|
|
|
torsoAngles[1] = v23;
|
|
|
|
if (v23 <= 30.0)
|
|
|
|
{
|
|
|
|
v71 = torsoAngles[1];
|
|
|
|
if (torsoAngles[1] >= -30.0)
|
|
|
|
{
|
|
|
|
fAng5 = fAng4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
torsoAngles[1] = -30.0;
|
|
|
|
fAng5 = fAng4 - (v71 + 30.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
torsoAngles[1] = 30.0;
|
|
|
|
fAng5 = fAng4 - (v23 - 30.0);
|
|
|
|
}
|
|
|
|
this->m_fTorsoCurrentTurnSpeed = fAng5;
|
|
|
|
v25 = fAng5;
|
|
|
|
v26 = v12;
|
|
|
|
torsoAngles[0] = 0.0;
|
|
|
|
torsoAngles[2] = 0.0;
|
|
|
|
SetControllerAngles(1, torsoAngles);
|
|
|
|
v4 = LocalLookAngles[0];
|
|
|
|
fAng6 = v26 - v25;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_25:
|
|
|
|
if (fAng6 > 15.0)
|
|
|
|
{
|
|
|
|
v28 = fAng6 - 15.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_27:
|
|
|
|
v29 = level.frametime;
|
|
|
|
fAng7 = v28 * 4.0 * v29;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_28;
|
|
|
|
}
|
|
|
|
if (-15.0 > fAng6)
|
|
|
|
{
|
|
|
|
v28 = fAng6 + 15.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_27;
|
|
|
|
}
|
|
|
|
v29 = level.frametime;
|
|
|
|
fAng7 = 0.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_28:
|
|
|
|
fAng8 = fAng6;
|
|
|
|
v32 = fAng6;
|
|
|
|
fAng9 = -headAngles[1];
|
|
|
|
if (v32 > fAng9)
|
|
|
|
{
|
|
|
|
fAng8 = fAng9;
|
|
|
|
fAng9 = v32;
|
|
|
|
}
|
|
|
|
if (fAng8 <= fAng7)
|
|
|
|
{
|
|
|
|
if (fAng7 <= fAng9)
|
|
|
|
{
|
|
|
|
v34 = headAngles[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v68 = v29;
|
|
|
|
v69 = fAng9;
|
|
|
|
v34 = headAngles[1];
|
|
|
|
v70 = v69;
|
|
|
|
v29 = v68;
|
|
|
|
fAng7 = v70;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng7 = fAng8;
|
|
|
|
v34 = headAngles[1];
|
|
|
|
}
|
|
|
|
v35 = this->m_fHeadMaxTurnSpeed;
|
|
|
|
v36 = -(v29 * v35);
|
|
|
|
if (v36 <= fAng7)
|
|
|
|
{
|
|
|
|
v67 = fAng7;
|
|
|
|
fAng10 = v29 * v35;
|
|
|
|
if (v67 <= fAng10)
|
|
|
|
fAng10 = v67;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng10 = v36;
|
|
|
|
}
|
|
|
|
v38 = v34;
|
|
|
|
v39 = this->m_fHeadMaxTurnSpeed;
|
|
|
|
v40 = fAng10 + v38;
|
|
|
|
v41 = 60.0;
|
|
|
|
headAngles[1] = v40;
|
|
|
|
if (v40 > 60.0)
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_37;
|
|
|
|
v42 = v29;
|
|
|
|
if (headAngles[1] < -60.0)
|
|
|
|
{
|
|
|
|
v41 = -60.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_37:
|
|
|
|
v43 = v29;
|
|
|
|
v44 = v41;
|
|
|
|
v42 = v43;
|
|
|
|
headAngles[1] = v44;
|
|
|
|
}
|
|
|
|
v45 = v42;
|
|
|
|
v46 = v4;
|
|
|
|
v47 = v45;
|
|
|
|
v48 = fabs(v46);
|
|
|
|
if (v48 >= 15.0)
|
|
|
|
{
|
|
|
|
fAng11 = 15.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fDist = v48;
|
|
|
|
fAng11 = fDist;
|
|
|
|
}
|
|
|
|
if (v176 > fAng11)
|
|
|
|
{
|
|
|
|
v50 = v176 - fAng11;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_42:
|
|
|
|
fDist = 0.2 * v50;
|
|
|
|
fAng12 = fDist;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_43;
|
|
|
|
}
|
|
|
|
if (-fAng11 > v176)
|
|
|
|
{
|
|
|
|
v50 = fAng11 + v176;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_42;
|
|
|
|
}
|
|
|
|
fAng12 = 0.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_43:
|
|
|
|
v52 = fAng12;
|
|
|
|
v53 = v47;
|
|
|
|
v54 = v52;
|
|
|
|
v55 = v39 * v53;
|
|
|
|
if (-v55 <= v52)
|
|
|
|
{
|
|
|
|
v65 = v55;
|
|
|
|
v66 = v54;
|
|
|
|
fAng13 = v65;
|
|
|
|
if (v66 <= v65)
|
|
|
|
fAng13 = v66;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng13 = -v55;
|
|
|
|
}
|
|
|
|
v57 = fAng13 + headAngles[0];
|
|
|
|
v58 = 35.0;
|
|
|
|
headAngles[0] = v57;
|
|
|
|
if (v57 > 35.0 || (v58 = -35.0, headAngles[0] < -35.0))
|
|
|
|
headAngles[0] = v58;
|
|
|
|
headAngles[2] = 0.0;
|
|
|
|
if (this->m_iLookFlags & 1)
|
|
|
|
{
|
|
|
|
headAngles[0] = 0.5 * headAngles[0];
|
|
|
|
headAngles[1] = 0.5 * headAngles[1];
|
|
|
|
}
|
|
|
|
SetControllerAngles(0, headAngles);
|
|
|
|
v177[0] = 0.0;
|
|
|
|
v177[1] = 0.0;
|
|
|
|
v177[2] = 0.0;
|
|
|
|
v178[0] = 0.0;
|
|
|
|
v178[1] = 0.0;
|
|
|
|
v178[2] = 0.0;
|
|
|
|
GetControllerAngles(2).copyTo(v177);
|
|
|
|
v179 = v177[0];
|
|
|
|
v180 = v177[1];
|
|
|
|
v181 = v177[2];
|
|
|
|
v59 = m_vLUpperArmDesiredAngles[1] - v180;
|
|
|
|
v60 = v59;
|
|
|
|
if (v59 <= 180.0)
|
|
|
|
{
|
|
|
|
if (v59 < -180.0)
|
|
|
|
v60 = v59 + 360.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v60 = v59 - 360.0;
|
|
|
|
}
|
|
|
|
v61 = this->m_fLUpperArmTurnSpeed * level.frametime;
|
|
|
|
if (-v61 <= v60)
|
|
|
|
{
|
|
|
|
v63 = v61;
|
|
|
|
v64 = v60;
|
|
|
|
fAng15 = v63;
|
|
|
|
if (v64 <= v63)
|
|
|
|
fAng15 = v64;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng15 = -v61;
|
|
|
|
}
|
|
|
|
v178[0] = this->m_vLUpperArmDesiredAngles[0];
|
|
|
|
v178[1] = fAng15 + v177[1];
|
|
|
|
v178[2] = 0.0;
|
|
|
|
SetControllerAngles(2, v178);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::setOriginEvent
|
|
|
|
(
|
|
|
|
Vector org
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
bool bRejoin = false;
|
|
|
|
//FIXME: macro
|
|
|
|
if ((org - origin).lengthSquared() > Square(1024))
|
|
|
|
{
|
|
|
|
bRejoin = true;
|
|
|
|
DisbandSquadMate(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_iOriginTime = level.inttime;
|
|
|
|
|
|
|
|
VectorCopy2D(org, m_vOriginHistory[0]);
|
|
|
|
VectorCopy2D(org, m_vOriginHistory[1]);
|
|
|
|
VectorCopy2D(org, m_vOriginHistory[2]);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorClear(velocity);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (level.Spawned())
|
|
|
|
{
|
|
|
|
SafeSetOrigin(org);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setOrigin(org);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vHome = origin;
|
|
|
|
|
|
|
|
if (bRejoin)
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
JoinNearbySquads();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SafeSetOrigin
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Safe set origin.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SafeSetOrigin
|
|
|
|
(
|
|
|
|
vec3_t newOrigin
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (newOrigin == origin)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
setOrigin(newOrigin);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!m_bNoPlayerCollision)
|
|
|
|
{
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
if (p && IsTouching(p))
|
|
|
|
{
|
|
|
|
Com_Printf("(entnum %d, radnum %d) is going not solid to not get stuck in the player\n", entnum, radnum);
|
|
|
|
m_bNoPlayerCollision = true;
|
|
|
|
setSolidType(SOLID_NOT);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DoMove
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move the actor based on m_eAnimMode.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DoMove
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
mmove_t mm;
|
|
|
|
//FIXME: macros
|
|
|
|
if (m_bDoPhysics
|
|
|
|
&& m_iOriginTime != level.inttime
|
|
|
|
&& !m_pGlueMaster
|
|
|
|
&& !bindmaster)
|
|
|
|
{
|
|
|
|
switch (m_eAnimMode)
|
|
|
|
{
|
|
|
|
case 1://normal i guess ?
|
|
|
|
{
|
|
|
|
SetMoveInfo(&mm);
|
|
|
|
|
|
|
|
VectorCopy2D(frame_delta, mm.desired_dir);
|
|
|
|
float frameDeltaLen = VectorNormalize2D(mm.desired_dir);
|
|
|
|
|
|
|
|
mm.desired_speed = frameDeltaLen / level.frametime;
|
|
|
|
|
|
|
|
if (mm.desired_speed > m_maxspeed)
|
|
|
|
mm.desired_speed = m_maxspeed;
|
|
|
|
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2://path
|
|
|
|
{
|
|
|
|
MovePath(frame_delta.length() / level.frametime);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3://path_goal (end) ?
|
|
|
|
{
|
|
|
|
MovePathGoal(frame_delta.length() / level.frametime);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4://dest
|
|
|
|
{
|
|
|
|
MoveDest(frame_delta.length() / level.frametime);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5://scripted
|
|
|
|
{
|
|
|
|
trace_t trace;
|
|
|
|
trace = G_Trace(origin, mins, maxs, frame_delta + origin, this, edict->clipmask & 0xF9FFE47D, qtrue, "Actor");
|
|
|
|
SafeSetOrigin(trace.endpos);
|
|
|
|
velocity = frame_delta / level.frametime;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6://noclip
|
|
|
|
{
|
|
|
|
SafeSetOrigin(frame_delta+origin);
|
|
|
|
velocity = frame_delta / level.frametime;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7://falling path
|
|
|
|
{
|
|
|
|
SafeSetOrigin(m_pFallPath->pos[m_pFallPath->currentPos]);
|
|
|
|
m_pFallPath->currentPos++;
|
|
|
|
velocity = vec_zero;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_maxspeed = 1000000.0f;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateAngles
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update current angles.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateAngles
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float max_change, error, dist;
|
|
|
|
|
|
|
|
if (!m_YawAchieved)
|
|
|
|
{
|
|
|
|
|
|
|
|
error = m_DesiredYaw - angles[1];
|
|
|
|
if (error <= 180)
|
|
|
|
{
|
|
|
|
if (error < -180.0)
|
|
|
|
error += 360;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error -= 360;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist = m_fAngleYawSpeed * level.frametime;
|
|
|
|
if (-dist <= error)
|
|
|
|
{
|
|
|
|
max_change = dist;
|
|
|
|
if (error <= dist)
|
|
|
|
{
|
|
|
|
max_change = error;
|
|
|
|
StopTurning();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
max_change = -dist;
|
|
|
|
}
|
|
|
|
setAngles(Vector{0, angles[1] + max_change, 0});
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetLeashHome
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set leash home.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetLeashHome
|
|
|
|
(
|
|
|
|
Vector vHome
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!m_bFixedLeash)
|
|
|
|
{
|
|
|
|
m_vHome = vHome;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GunPosition
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns current gun position.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector Actor::GunPosition
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_iGunPositionCheckTime < level.inttime)
|
|
|
|
{
|
|
|
|
m_iGunPositionCheckTime = level.inttime;
|
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
if (weap)
|
|
|
|
{
|
|
|
|
weap->GetMuzzlePosition(m_vGunPosition);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_vGunPosition = vec_zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return m_vGunPosition;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanSee
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor cansee entity through fov and vision_distance.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSee
|
|
|
|
(
|
|
|
|
Entity *e1,
|
|
|
|
float fov,
|
|
|
|
float vision_distance,
|
|
|
|
bool bNoEnts
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bool canSee = Sentient::CanSee(e1, fov, vision_distance, false);
|
|
|
|
if (e1 == m_Enemy)
|
|
|
|
{
|
|
|
|
m_iEnemyVisibleCheckTime = level.inttime;
|
|
|
|
if (canSee)
|
|
|
|
{
|
|
|
|
SetEnemyPos(e1->origin);
|
|
|
|
m_bEnemyIsDisguised = m_Enemy->m_bIsDisguised;
|
|
|
|
m_iEnemyCheckTime = level.inttime;
|
|
|
|
m_iLastEnemyVisibleTime = level.inttime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (canSee != m_bEnemyVisible)
|
|
|
|
{
|
|
|
|
m_bEnemyVisible = true;
|
|
|
|
m_iEnemyVisibleChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fov != 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
m_iEnemyFovCheckTime = level.inttime;
|
|
|
|
if (canSee != m_bEnemyInFOV)
|
|
|
|
{
|
|
|
|
m_bEnemyInFOV = true;
|
|
|
|
m_iEnemyFovChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return canSee;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanShoot
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can shoot entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanShoot
|
|
|
|
(
|
|
|
|
Entity *ent
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bool bCanShootEnemy = false;
|
|
|
|
if (ent->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
Sentient * sen = (Sentient *)ent;
|
|
|
|
//FIXME: macro.
|
|
|
|
if (world->farplane_distance == 0 || Square(world->farplane_distance * 0.828) > (origin - sen->origin).lengthSquared())
|
|
|
|
{
|
|
|
|
if (gi.AreasConnected(
|
|
|
|
edict->r.areanum,
|
|
|
|
sen->edict->r.areanum))
|
|
|
|
{
|
|
|
|
if (G_SightTrace(
|
|
|
|
GunPosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
sen->centroid,
|
|
|
|
this,
|
|
|
|
sen,
|
|
|
|
MASK_CANSEE,
|
|
|
|
qfalse,
|
|
|
|
"Actor::CanShoot centroid")
|
|
|
|
|| G_SightTrace(
|
|
|
|
GunPosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
sen->EyePosition(),
|
|
|
|
this,
|
|
|
|
sen,
|
|
|
|
MASK_CANSEE,
|
|
|
|
qfalse,
|
|
|
|
"Actor::CanShoot eyes"))
|
|
|
|
{
|
|
|
|
bCanShootEnemy = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
m_bCanShootEnemy = bCanShootEnemy;
|
|
|
|
m_iCanShootCheckTime = level.inttime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
if (gi.AreasConnected(
|
|
|
|
edict->r.areanum,
|
|
|
|
ent->edict->r.areanum))
|
|
|
|
{
|
|
|
|
if (CanSeeFrom(GunPosition(), ent))
|
|
|
|
{
|
|
|
|
bCanShootEnemy = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bCanShootEnemy;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanSeeFrom
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can see entity from pos.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSeeFrom
|
|
|
|
(
|
|
|
|
vec3_t pos,
|
|
|
|
Entity *ent
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vPos(pos);
|
|
|
|
bool bCanSee = false;
|
|
|
|
if (world->farplane_distance == 0 || Square(world->farplane_distance * 0.828) > (origin - ent->origin).lengthSquared())
|
|
|
|
{
|
|
|
|
if (!ent->IsSubclassOfActor() && G_SightTrace(vPos, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, qfalse, "Actor::CanSeeFrom"))
|
|
|
|
{
|
|
|
|
bCanSee = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bCanSee;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EnemyInFOV
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if enemy is within fov.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::EnemyInFOV
|
|
|
|
(
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyFovCheckTime)
|
|
|
|
{
|
|
|
|
bool bInFov = InFOV(m_Enemy->centroid, m_fFov, m_fFovDot);
|
|
|
|
if (m_bEnemyInFOV != bInFov)
|
|
|
|
{
|
|
|
|
m_bEnemyInFOV = !m_bEnemyInFOV;
|
|
|
|
m_iEnemyFovChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
m_iEnemyFovCheckTime = level.inttime;
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
return m_iEnemyFovCheckTime;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanSeeEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can see enemy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSeeEnemy
|
|
|
|
(
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyVisibleCheckTime)
|
|
|
|
CanSee(m_Enemy, 0, 0.828 * world->farplane_distance, false);
|
|
|
|
|
|
|
|
return m_bEnemyVisible;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanShootEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can shoot enemy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanShootEnemy
|
|
|
|
(
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if( level.inttime > iMaxDirtyTime + m_iCanShootCheckTime )
|
|
|
|
CanShoot( m_Enemy );
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return m_bCanShootEnemy;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::TransitionState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::TransitionState
|
|
|
|
(
|
|
|
|
int iNewState,
|
|
|
|
int iPadTime
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//fixme: this is an inline function.
|
|
|
|
m_State = iNewState;
|
|
|
|
m_iStateTime = level.inttime + iPadTime;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanSee
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true to script if actor cansee entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::CanSee
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fov = 0;
|
|
|
|
float vision_distance = 0;
|
|
|
|
|
|
|
|
if (m_Think[m_ThinkLevel] != THINK_MACHINEGUNNER || !m_pTurret)
|
|
|
|
{
|
|
|
|
return Entity::CanSee(ev);
|
|
|
|
}
|
|
|
|
switch (ev->NumArgs())
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
//do nothing
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
fov = ev->GetFloat(2);
|
|
|
|
if (fov < 0 || fov> 360)
|
|
|
|
{
|
|
|
|
ScriptError("fov must be in range 0 <= fov <= 360");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
vision_distance = ev->GetFloat(3);
|
|
|
|
if (vision_distance < 0)
|
|
|
|
{
|
|
|
|
ScriptError("vision distance must be >= 0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
ScriptError("cansee should have 1, 2, or 3 arguments");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Entity *ent = ev->GetEntity(1);
|
|
|
|
if (!ent)
|
|
|
|
{
|
|
|
|
ScriptError("NULL entity in parameter 1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int cansee = MachineGunner_CanSee(ent, fov, vision_distance);
|
|
|
|
ev->AddInteger(cansee);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ExtractConstraints
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ExtractConstraints
|
|
|
|
(
|
|
|
|
mmove_t *mm
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
// not found in ida
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::FireWeapon
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Fire weapon from script.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FireWeapon
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Sentient::FireWeapon(WEAPON_MAIN, FIRE_PRIMARY);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsMachineGunnerState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsDogState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IgnoreSoundSet
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Make actor ignore iType sound.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IgnoreSoundSet
|
|
|
|
(
|
|
|
|
int iType
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iIgnoreSoundsMask |= 1 << iType;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IgnoreSoundSetAll
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Make actor ignore all types of sound.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IgnoreSoundSetAll
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iIgnoreSoundsMask = ~AI_EVENT_NONE;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-05 16:55:10 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IgnoreSoundClear
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Don't ignore iType of sound.
|
2018-09-05 16:55:10 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IgnoreSoundClear
|
|
|
|
(
|
|
|
|
int iType
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iIgnoreSoundsMask &= ~iType;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::IgnoreSoundClearAll
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Make actor ignore no type of sound.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::IgnoreSoundClearAll
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_iIgnoreSoundsMask = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IgnoreSoundClearAll
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
returns true if actor should ignore iType of sound.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IgnoreSound
|
|
|
|
(
|
|
|
|
int iType
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return ( m_iIgnoreSoundsMask >> iType ) & 1;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::WithinVisionDistance
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if entity is witthin vision distance.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::WithinVisionDistance
|
|
|
|
(
|
|
|
|
Entity *ent
|
|
|
|
) const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float fRadius = world->m_fAIVisionDistance;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if(fRadius == 0 )
|
|
|
|
{
|
|
|
|
fRadius = m_fSight;
|
|
|
|
}
|
|
|
|
else if( m_fSight <= fRadius )
|
|
|
|
{
|
|
|
|
fRadius = m_fSight;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( ent )
|
|
|
|
{
|
|
|
|
Vector vDelta = ent->origin - origin;
|
|
|
|
//it's basically the same as vDelta.length() < fRadius,
|
|
|
|
//but this is faster because sqrt in vDelta.length() is slower than multiplication.
|
|
|
|
return vDelta.lengthSquared() < Square(fRadius);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::InFOV
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if positin is within fov.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::InFOV
|
|
|
|
(
|
|
|
|
Vector pos,
|
|
|
|
float check_fov,
|
|
|
|
float check_fovdot
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
bool bInFov = true;
|
|
|
|
if (check_fov != 360.0)
|
|
|
|
{
|
|
|
|
Vector delta = pos - EyePosition();
|
|
|
|
if (delta.x == 0 && delta.y == 0)
|
|
|
|
{
|
|
|
|
return bInFov;
|
|
|
|
}
|
|
|
|
bInFov = false;
|
|
|
|
|
|
|
|
|
|
|
|
float fDot = DotProduct2D(delta, orientation[0]);
|
|
|
|
if (fDot >= 0)
|
|
|
|
{
|
|
|
|
bInFov = Square(fDot) > delta.lengthXYSquared() * Square(check_fovdot);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return bInFov;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::InFOV
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if pos is within fov.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::InFOV
|
|
|
|
(
|
|
|
|
Vector pos
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return InFOV(pos, m_fFov, m_fFovDot);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::InFOV
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if ent is within fov.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::InFOV
|
|
|
|
(
|
|
|
|
Entity *ent
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ent == m_Enemy)
|
|
|
|
{
|
|
|
|
return EnemyInFOV(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return InFOV(ent->centroid, m_fFov, m_fFovDot);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSeeNoFOV
|
|
|
|
(
|
|
|
|
Entity *ent
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (ent == m_Enemy)
|
|
|
|
{
|
|
|
|
return CanSeeEnemy(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool bCanSee = false;
|
|
|
|
if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum))
|
|
|
|
{
|
|
|
|
bCanSee = CanSeeFrom(EyePosition(), ent);
|
|
|
|
}
|
|
|
|
return bCanSee;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSeeFOV
|
|
|
|
(
|
|
|
|
Entity *ent
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//fixme: this is an inline function.
|
|
|
|
if (ent == m_Enemy)
|
|
|
|
{
|
|
|
|
return CanSeeEnemyFOV(0, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool bCanSee = false;
|
|
|
|
if (InFOV(ent->centroid, m_fFov, m_fFovDot) && gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum))
|
|
|
|
{
|
|
|
|
bCanSee = CanSeeFrom(EyePosition(), ent);
|
|
|
|
}
|
|
|
|
return bCanSee;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanSeeEnemyFOV
|
|
|
|
(
|
|
|
|
int iMaxFovDirtyTime,
|
|
|
|
int iMaxSightDirtyTime
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return EnemyInFOV(iMaxFovDirtyTime) && CanSeeEnemy(iMaxSightDirtyTime);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CanTarget
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor can target.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::CanTarget
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IsImmortal
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor is immortal ?
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsImmortal
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::ShowInfo
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Prints basic actor information.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::ShowInfo
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Com_Printf( "-------------------------------------------------------------------------------\n" );
|
|
|
|
Com_Printf( "Info for Actor:\n" );
|
|
|
|
Com_Printf( "Current think type: %s %s\n", ThinkName().c_str(), ThinkStateName().c_str() );
|
|
|
|
Com_Printf( "leash: %f\n", m_fLeash );
|
|
|
|
Com_Printf( "mindist: %f\n", m_fMinDistance );
|
|
|
|
Com_Printf( "maxdist: %f\n", m_fMaxDistance );
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ];
|
|
|
|
if( func->ShowInfo )
|
|
|
|
( this->*func->ShowInfo )( );
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf( "-------------------------------------------------------------------------------\n" );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ShowInfo
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Display actor info.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ShowInfo
|
|
|
|
(
|
|
|
|
float fDot,
|
|
|
|
float fDist
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fMaxDist, fMinDot;
|
|
|
|
static cvar_t *g_entinfo_max;
|
|
|
|
|
|
|
|
if (!bEntinfoInit)
|
|
|
|
{
|
|
|
|
g_entinfo_max = gi.Cvar_Get("g_entinfo_max", "2048", 0);
|
|
|
|
bEntinfoInit = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
fMinDot = 0.9f;
|
|
|
|
fMaxDist = g_entinfo_max->value;
|
|
|
|
|
|
|
|
if ( IsKilledState(m_ThinkState) )
|
|
|
|
{
|
|
|
|
fMinDot = 0.99f;
|
|
|
|
fMaxDist = 512;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_entinfo->integer != 4)
|
|
|
|
{
|
|
|
|
if (fDot <= fMinDot)
|
|
|
|
{
|
|
|
|
if (fDot <= 0 || fDist >= 256)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fMaxDist <= fDist || fDist <= 64)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 74;
|
|
|
|
|
|
|
|
G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "DISABLED");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 56;
|
|
|
|
|
|
|
|
|
|
|
|
G_DebugString(
|
|
|
|
a,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
"%i:%i:%s:%.1f",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
health);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 38;
|
|
|
|
|
|
|
|
|
|
|
|
G_DebugString(
|
|
|
|
a,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
"%i:%s:%.1f:%i",
|
|
|
|
m_Enemy->entnum,
|
|
|
|
m_Enemy->targetname.c_str(),
|
|
|
|
m_Enemy->health,
|
|
|
|
m_PotentialEnemies.GetCurrentThreat());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( IsCuriousState(m_ThinkState) )
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 20;
|
|
|
|
|
|
|
|
|
|
|
|
G_DebugString(
|
|
|
|
a,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
"%s:%%%.1f",
|
|
|
|
Director.GetString(m_csThinkStateNames[THINKSTATE_CURIOUS]).c_str(),
|
|
|
|
m_PotentialEnemies.GetCurrentVisibility() * 100);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 20;
|
|
|
|
|
|
|
|
|
|
|
|
G_DebugString(
|
|
|
|
a,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
"%s",
|
|
|
|
ThinkStateName().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 2;
|
|
|
|
|
|
|
|
str sAnimThreadFile = m_pAnimThread ? m_pAnimThread->FileName() : "(null)";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
G_DebugString(
|
|
|
|
a,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
"%s:%s:%i - %s",
|
|
|
|
ThinkName().c_str(),
|
|
|
|
m_pszDebugState,
|
|
|
|
m_State,
|
|
|
|
sAnimThreadFile.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_entinfo->integer == 1)
|
|
|
|
{
|
|
|
|
if (m_pGrenade)
|
|
|
|
G_DebugLine(m_pGrenade->origin, m_vGrenadePos, 1.0, 0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
Vector a = m_vHome;
|
|
|
|
a.z += maxs.z + 18;
|
|
|
|
|
|
|
|
G_DebugLine(centroid, a, 0.0, 1.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
G_DebugCircle(a, m_fLeash, 0.0, 1.0, 0.0, 1.0, qtrue);
|
|
|
|
|
|
|
|
G_DebugCircle(
|
|
|
|
centroid,
|
|
|
|
m_fMinDistance,
|
|
|
|
1.0,
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
qtrue);
|
|
|
|
|
|
|
|
G_DebugCircle(
|
|
|
|
centroid,
|
|
|
|
m_fMaxDistance,
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
qtrue);
|
|
|
|
}
|
|
|
|
else if (g_entinfo->integer == 2)
|
|
|
|
{
|
|
|
|
G_DebugCircle(
|
|
|
|
centroid,
|
|
|
|
m_fHearing,
|
|
|
|
1.0,
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
qtrue);
|
|
|
|
G_DebugCircle(
|
|
|
|
centroid,
|
|
|
|
m_fSight,
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
qtrue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
str Actor::ThinkName
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return Director.GetString( m_csThinkNames[ m_Think[ m_ThinkLevel ] ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
str Actor::ThinkStateName
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
return Director.GetString( m_csThinkStateNames[ m_ThinkState ] );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MoveTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move actor to specific location/listener with specific animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::MoveTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csPatrolCurrentAnim = ev->GetConstString( 1 );
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( ev->IsVectorAt( 2 ) )
|
|
|
|
{
|
|
|
|
Vector vec = ev->GetVector( 2 );
|
|
|
|
SetPatrolCurrentNode( vec );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetPatrolCurrentNode( ev->GetListener( 2 ) );
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_patrolCurrentNode )
|
|
|
|
{
|
|
|
|
m_vScriptGoal = origin;
|
|
|
|
m_bScriptGoalValid = true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_RUNNER);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::WalkTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Walk to specific location.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::WalkTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event event = EV_Listener_ExecuteScript;
|
|
|
|
event.AddConstString( STRING_GLOBAL_WALKTO_SCR );
|
|
|
|
event.AddValue( ev->GetValue( 1 ) );
|
|
|
|
ExecuteScript( &event );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::RunTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Run to specific location.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::RunTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event event = EV_Listener_ExecuteScript;
|
|
|
|
event.AddConstString( STRING_GLOBAL_RUNTO_SCR );
|
|
|
|
event.AddValue( ev->GetValue( 1 ) );
|
|
|
|
ExecuteScript( &event );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2019-08-18 22:06:49 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CrouchTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Crouch to specific location.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::CrouchTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event event = EV_Listener_ExecuteScript;
|
|
|
|
event.AddConstString( STRING_GLOBAL_CROUCHTO_SCR );
|
|
|
|
event.AddValue( ev->GetValue( 1 ) );
|
|
|
|
ExecuteScript( &event );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CrawlTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Crawl to specific location.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::CrawlTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event event = EV_Listener_ExecuteScript;
|
|
|
|
event.AddConstString( STRING_GLOBAL_CRAWLTO_SCR );
|
|
|
|
event.AddValue( ev->GetValue( 1 ) );
|
|
|
|
ExecuteScript( &event );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearAimNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear aim node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearAimNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_aimNode)
|
|
|
|
{
|
2019-06-29 23:43:30 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_aimNode->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_aimNode;
|
|
|
|
}
|
|
|
|
m_aimNode = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetAimNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change aim node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetAimNode
|
|
|
|
(
|
|
|
|
Vector& vec
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearAimNode();
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
TempWaypoint * twp = new TempWaypoint();
|
|
|
|
m_aimNode = twp;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_aimNode->setOrigin(vec);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetAimNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change aim node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetAimNode
|
|
|
|
(
|
|
|
|
Listener *l
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearAimNode();
|
|
|
|
if (l)
|
|
|
|
{
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError(
|
|
|
|
"Bad aim node with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z);
|
|
|
|
}
|
|
|
|
m_aimNode = (SimpleEntity *)l;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::AimAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Aim at specified target.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::AimAt
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( ev->IsVectorAt( 1 ) )
|
|
|
|
{
|
|
|
|
Vector orig = ev->GetVector(1);
|
|
|
|
if (m_aimNode)
|
|
|
|
{
|
|
|
|
if (m_aimNode->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_aimNode;
|
|
|
|
}
|
|
|
|
m_aimNode = NULL;
|
|
|
|
}
|
|
|
|
TempWaypoint * twp = new TempWaypoint;
|
|
|
|
m_aimNode = twp;
|
|
|
|
m_aimNode->setOrigin(orig);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetAimNode(ev->GetListener(1));
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle( m_aimNode != NULL ? THINK_AIM : THINK_IDLE);
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::LookAtLookEntity
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change current look entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::LookAtLookEntity
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector dir;
|
|
|
|
if (m_pLookEntity->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
dir = ((Sentient *)m_pLookEntity.Pointer())->EyePosition() - EyePosition();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dir = m_pLookEntity->centroid - EyePosition();
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredLookDir(dir);
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IdleLook
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Idle look behaviour.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IdleLook
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pLookEntity)
|
|
|
|
{
|
|
|
|
LookAtLookEntity();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IdleLook
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Idle look behaviour.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IdleLook
|
|
|
|
(
|
|
|
|
vec3_t dir
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pLookEntity)
|
|
|
|
{
|
|
|
|
LookAtLookEntity();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetDesiredLookDir(dir);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearLookEntity
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear look entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearLookEntity
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pLookEntity)
|
|
|
|
{
|
|
|
|
if (m_pLookEntity->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_pLookEntity;
|
|
|
|
}
|
|
|
|
m_pLookEntity = NULL;
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::LookAt
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change current look entity.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::LookAt
|
|
|
|
(
|
|
|
|
const Vector& vec
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (g_showlookat->integer == entnum || g_showlookat->integer == -1)
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
vec.x,
|
|
|
|
vec.y,
|
|
|
|
vec.z);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearLookEntity();
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
TempWaypoint *twp = new TempWaypoint();
|
|
|
|
m_pLookEntity = twp;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pLookEntity->setOrigin(vec);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::LookAt
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change current look entity.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::LookAt
|
|
|
|
(
|
|
|
|
Listener *l
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ClearLookEntity();
|
|
|
|
if ( l )
|
|
|
|
{
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError("Bad look entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (l != this)
|
|
|
|
{
|
|
|
|
l = (SimpleEntity*)l;
|
|
|
|
if (g_showlookat->integer == entnum || g_showlookat->integer == -1)
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
((SimpleEntity*)l)->origin.x,
|
|
|
|
((SimpleEntity*)l)->origin.y,
|
|
|
|
((SimpleEntity*)l)->origin.z);
|
|
|
|
}
|
|
|
|
m_pLookEntity = (SimpleEntity*)l;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventLookAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Look at event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventLookAt
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ev->IsVectorAt(1))
|
|
|
|
{
|
|
|
|
LookAt(ev->GetVector(1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LookAt(ev->GetListener(1));
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iLookFlags = 0;//LOOK_NORMAL
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventEyesLookAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Eyes look at event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventEyesLookAt
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
EventLookAt(ev);
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iLookFlags = 1;//LOOK_EYE
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::NoPoint
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Don't point at anything.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::NoPoint
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorClear(m_vLUpperArmDesiredAngles);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IdlePoint
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Idle point behaviour.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IdlePoint
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_pPointEntity)
|
|
|
|
{
|
|
|
|
Vector delta = m_pPointEntity->centroid - origin;
|
|
|
|
Vector v2;
|
|
|
|
VectorNormalize(delta);
|
|
|
|
v2 = delta.toAngles();
|
|
|
|
|
|
|
|
float yaw = AngleNormalize180(v2[1] - angles[1] + 30);
|
|
|
|
if (yaw > 100)
|
|
|
|
yaw = 100;
|
|
|
|
if (yaw < -80)
|
|
|
|
yaw = -80;
|
|
|
|
m_vLUpperArmDesiredAngles[0] = v2[0];
|
|
|
|
m_vLUpperArmDesiredAngles[1] = yaw;
|
|
|
|
m_vLUpperArmDesiredAngles[2] = v2[2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NoPoint();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearPointEntity
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear point entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearPointEntity
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pPointEntity)
|
|
|
|
{
|
|
|
|
if (m_pPointEntity->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_pPointEntity;
|
|
|
|
}
|
|
|
|
m_pPointEntity = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PointAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change point entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PointAt
|
|
|
|
(
|
|
|
|
const Vector& vec
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPointEntity();
|
|
|
|
|
|
|
|
TempWaypoint *twp = new TempWaypoint();
|
|
|
|
m_pPointEntity = twp;
|
|
|
|
m_pPointEntity->setOrigin(vec);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PointAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change point entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PointAt
|
|
|
|
(
|
|
|
|
Listener* l
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ClearPointEntity();
|
|
|
|
if (l)
|
|
|
|
{
|
|
|
|
if (l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError("Bad point entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z);
|
|
|
|
}
|
|
|
|
if (l != this)
|
|
|
|
{
|
|
|
|
m_pPointEntity = (SimpleEntity *)l;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventPointAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Point at event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventPointAt
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ev->IsVectorAt(1))
|
|
|
|
{
|
|
|
|
|
|
|
|
PointAt(ev->GetVector(1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PointAt(ev->GetListener(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::IdleTurn
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Idle turn behaviour.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::IdleTurn
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pTurnEntity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i <= 1; i++)
|
|
|
|
{
|
|
|
|
if (m_pTurnEntity == this)
|
|
|
|
{
|
|
|
|
StopTurning();
|
|
|
|
m_pTurnEntity = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vec2_t facedir;
|
|
|
|
VectorSub2D(m_pTurnEntity->centroid, origin, facedir);
|
|
|
|
if (facedir[0] || facedir[1])
|
|
|
|
{
|
|
|
|
SetDesiredYawDir(facedir);
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
float error = AngleNormalize180(m_DesiredYaw - angles[1]);
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (error >= m_fTurnDoneError + 0.001 || -(m_fTurnDoneError + 0.001) >= error)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SafePtr<SimpleEntity> prevTurnEntity = m_pTurnEntity;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Director.Unpause();
|
|
|
|
Unregister(STRING_TURNDONE);
|
|
|
|
Director.Pause();
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
if (m_pTurnEntity == prevTurnEntity)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearTurnEntity
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear turn entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearTurnEntity
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pTurnEntity)
|
|
|
|
{
|
|
|
|
if (m_pTurnEntity->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_pTurnEntity;
|
|
|
|
}
|
|
|
|
m_pTurnEntity = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::TurnTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change turn entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::TurnTo
|
|
|
|
(
|
|
|
|
const Vector& vec
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearTurnEntity();
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
TempWaypoint *twp = new TempWaypoint();
|
|
|
|
m_pTurnEntity = twp;
|
|
|
|
m_pTurnEntity->setOrigin(vec);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::TurnTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change turn entity.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::TurnTo
|
|
|
|
(
|
|
|
|
Listener *l
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearTurnEntity();
|
|
|
|
if (l)
|
|
|
|
{
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError("Bad turn entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pTurnEntity = (SimpleEntity *)l;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pTurnEntity = this;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventTurnTo
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Turn to event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventTurnTo
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ev->IsVectorAt(1))
|
|
|
|
{
|
|
|
|
TurnTo(ev->GetVector(1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TurnTo(ev->GetListener(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetTurnDoneError
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set the error amount that turndone will occur for the turnto command.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetTurnDoneError
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fTurnDoneError = ev->GetFloat(1);
|
|
|
|
if (m_fTurnDoneError < 0)
|
|
|
|
{
|
|
|
|
m_fTurnDoneError = 0;
|
|
|
|
ScriptError("turndoneerror was set to a negative value - capped to 0");
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetTurnDoneError
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get the error amount that turndone will occur for the turnto command.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetTurnDoneError
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fTurnDoneError);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventGiveWeaponInternal
|
|
|
|
|
|
|
|
Give weapon to actor.
|
|
|
|
|
|
|
|
Called from STRING_GLOBAL_WEAPON_SCR.
|
|
|
|
===============
|
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
void Actor::EventGiveWeaponInternal
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Holster();
|
|
|
|
RemoveWeapons();
|
|
|
|
str weapName = ev->GetString(1);
|
|
|
|
if (giveItem(weapName))
|
|
|
|
{
|
|
|
|
Unholster();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventGiveWeapon
|
|
|
|
|
|
|
|
Give weapon to actor.
|
|
|
|
===============
|
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
void Actor::EventGiveWeapon
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
str weapName = ev->GetString(1);
|
|
|
|
weapName.tolower();
|
|
|
|
const_str csWeapName = Director.AddString(weapName);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csLoadOut = csWeapName;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (csWeapName == STRING_MG42)
|
|
|
|
{
|
|
|
|
csWeapName = STRING_MP40;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csWeapon = csWeapName;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
setModel();
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
e1.AddConstString(STRING_GLOBAL_WEAPON_SCR);
|
|
|
|
e1.AddString(weapName);
|
|
|
|
glbs.Printf("EventGiveWeapon script: %s weapName: %s \n", Director.GetString(STRING_GLOBAL_WEAPON_SCR).c_str(), weapName.c_str());
|
|
|
|
ExecuteScript(&e1);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventGetWeapon
|
|
|
|
|
|
|
|
Returns weapon path to script.
|
|
|
|
===============
|
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
void Actor::EventGetWeapon
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csWeapon);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DefaultPain
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Default pain handler.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DefaultPain
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.Printf("DefaultPain event");
|
|
|
|
SetThink(THINKSTATE_PAIN, THINK_PAIN);
|
|
|
|
|
|
|
|
HandlePain(ev);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::HandlePain
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Hangled pain event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::HandlePain
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.Printf("HandlePain");
|
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
if (m_bEnablePain)
|
|
|
|
{
|
|
|
|
|
|
|
|
e1.AddConstString(STRING_GLOBAL_PAIN_SCR);
|
|
|
|
|
|
|
|
for (int i = 1; i <= ev->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
e1.AddValue(ev->GetValue(i));
|
|
|
|
}
|
|
|
|
ExecuteScript(&e1);
|
|
|
|
|
|
|
|
SetThinkState(THINKSTATE_PAIN, THINKLEVEL_PAIN);
|
|
|
|
|
|
|
|
RaiseAlertness(0.5);
|
|
|
|
|
|
|
|
m_PainTime = level.inttime;
|
|
|
|
|
|
|
|
Entity *ent = ev->GetEntity(1);
|
|
|
|
if (ent && ent->IsSubclassOfSentient() && !IsTeamMate((Sentient *)ent))
|
|
|
|
{
|
|
|
|
m_pLastAttacker = ent;
|
|
|
|
|
|
|
|
m_iCuriousLevel = 9;
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
SetCuriousAnimHint(7);
|
|
|
|
|
|
|
|
if (m_bEnableEnemy && m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE)
|
|
|
|
{
|
|
|
|
SetEnemyPos(ent->origin);
|
|
|
|
m_pszDebugState = "from_pain";
|
|
|
|
SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Unregister(STRING_PAIN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventPain
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Pain event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventPain
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ShowInfo();
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.Printf("pain event");
|
|
|
|
if (func->Pain)
|
|
|
|
(this->*func->Pain)(ev);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::DefaultKilled
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Default killed handler.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::DefaultKilled
|
|
|
|
(
|
|
|
|
Event *ev,
|
|
|
|
bool bPlayDeathAnim
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearStates();
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_KILLED, THINK_KILLED);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
HandleKilled(ev, bPlayDeathAnim);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::HandleKilled
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Hangled killed event.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::HandleKilled
|
|
|
|
(
|
|
|
|
Event *ev,
|
|
|
|
bool bPlayDeathAnim
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
deadflag = DEAD_DEAD;
|
|
|
|
health = 0.0;
|
|
|
|
if (bPlayDeathAnim)
|
|
|
|
{
|
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_KILLED_SCR);
|
|
|
|
for (int i = 1; i < ev->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
e1.AddValue(ev->GetValue(i));
|
|
|
|
}
|
|
|
|
ExecuteScript(&e1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetThink(THINKSTATE_KILLED, THINK_DEAD);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearThinkStates();
|
|
|
|
|
|
|
|
SetThinkState(THINKSTATE_KILLED, THINKLEVEL_KILLED);
|
|
|
|
|
|
|
|
gi.DPrintf("Waittill death unregisterd\n");
|
|
|
|
Unregister(STRING_DEATH);
|
|
|
|
Unregister(STRING_PAIN);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::DispatchEventKilled
|
|
|
|
|
|
|
|
Dispatch killed event.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::DispatchEventKilled
|
|
|
|
(
|
|
|
|
Event *ev,
|
|
|
|
bool bPlayDeathAnim
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
|
|
|
if (func->Killed)
|
|
|
|
(this->*func->Killed)(ev, bPlayDeathAnim);
|
|
|
|
|
|
|
|
SetEnemy(NULL, false);
|
|
|
|
|
|
|
|
DisbandSquadMate(this);
|
|
|
|
if (bPlayDeathAnim)
|
|
|
|
{
|
|
|
|
DropInventoryItems();
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventKilled
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Killed event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventKilled
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
DispatchEventKilled(ev, true);
|
|
|
|
|
|
|
|
Player *p1 = (Player *)ev->GetEntity(1);
|
|
|
|
if (p1)
|
|
|
|
{
|
|
|
|
if (p1->IsSubclassOfPlayer() && p1->m_Team == m_Team)
|
|
|
|
{
|
|
|
|
p1->m_iNumEnemiesKilled++;
|
|
|
|
}
|
|
|
|
if (p1->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
for (Sentient *pSent = level.m_HeadSentient[m_Team]; pSent; pSent = pSent->m_NextSentient)
|
|
|
|
{
|
|
|
|
if (pSent != this)
|
|
|
|
{
|
|
|
|
if (pSent->IsSubclassOfActor())
|
|
|
|
NotifySquadmateKilled(pSent, p1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventBeDead
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Become dead.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventBeDead
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
DispatchEventKilled(ev, false);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DeathEmbalm
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
preps the dead actor for turning nonsolid gradually over time
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DeathEmbalm
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (maxs[2] > 8)
|
|
|
|
{
|
|
|
|
maxs[2] -= 4;
|
|
|
|
if (maxs[2] > 8)
|
|
|
|
{
|
|
|
|
Event e1(EV_Actor_DeathEmbalm);
|
|
|
|
PostEvent(e1, 0.5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
maxs[2] = 8.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
setSize(mins, maxs);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DeathSinkStart
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Makes the actor sink into the ground and then get removed(this starts it).
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DeathSinkStart
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
flags &= ~FL_BLOOD;
|
|
|
|
|
|
|
|
setMoveType(MOVETYPE_NONE);
|
|
|
|
|
|
|
|
Entity::DeathSinkStart(ev);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PlayAnimation
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play animation
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PlayAnimation
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_ANIM_SCR);
|
|
|
|
e1.AddValue(ev->GetValue(1));
|
|
|
|
ExecuteScript(&e1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PlayScriptedAnimation
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play scripted animation
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PlayScriptedAnimation
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_ANIM_SCRIPTED_SCR);
|
|
|
|
e1.AddValue(ev->GetValue(1));
|
|
|
|
ExecuteScript(&e1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PlayNoclipAnimation
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play noclip animation
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PlayNoclipAnimation
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_ANIM_NOCLIP_SCR);
|
|
|
|
e1.AddValue(ev->GetValue(1));
|
|
|
|
ExecuteScript(&e1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MoveDest
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play noclip animation
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::MoveDest
|
|
|
|
(
|
|
|
|
float fMoveSpeed
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
mmove_t mm;
|
|
|
|
vec2_t offset;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetMoveInfo(&mm);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fMoveSpeed > m_maxspeed)
|
|
|
|
fMoveSpeed = m_maxspeed;
|
|
|
|
|
|
|
|
mm.desired_speed = fMoveSpeed;
|
|
|
|
|
|
|
|
VectorSub2D(m_Dest, origin, offset);
|
|
|
|
|
|
|
|
VectorNormalize2D2(offset, mm.desired_dir);
|
|
|
|
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
|
|
|
|
GetMoveInfo(&mm);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MovePath
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move on path.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::MovePath
|
|
|
|
(
|
|
|
|
float fMoveSpeed
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
mmove_t mm;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SetMoveInfo(&mm);
|
|
|
|
|
|
|
|
mm.desired_speed = fMoveSpeed;
|
|
|
|
if (mm.desired_speed > m_maxspeed)
|
|
|
|
{
|
|
|
|
mm.desired_speed = m_maxspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Path.UpdatePos(origin);
|
|
|
|
|
|
|
|
if (ai_debugpath->integer)
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector pos, dest;
|
|
|
|
pos = origin;
|
|
|
|
pos.z += 32;
|
|
|
|
dest = m_Path.CurrentDelta();
|
|
|
|
dest += origin;
|
|
|
|
dest.z += 32;
|
|
|
|
G_DebugLine(pos, dest, 1, 0, 0, 1);
|
|
|
|
for (PathInfo *current_path = m_Path.CurrentNode(); current_path != m_Path.LastNode(); current_path = m_Path.NextNode())
|
|
|
|
{
|
|
|
|
pos = current_path->point;
|
|
|
|
pos.z += 32;
|
|
|
|
|
|
|
|
dest = m_Path.NextNode()->point;
|
|
|
|
dest.z += 32;
|
|
|
|
G_DebugLine(pos, dest, 0, 1, 0, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy2D(m_Path.CurrentDelta(), mm.desired_dir);
|
|
|
|
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (!mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
if (m_WallDir)
|
|
|
|
{
|
|
|
|
if (level.inttime >= m_iWallDodgeTimeout)
|
|
|
|
{
|
|
|
|
m_WallDir = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0 && CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0)
|
|
|
|
{
|
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
|
|
|
m_WallDir = -m_WallDir;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
velocity.copyTo(mm.velocity);
|
|
|
|
origin.copyTo(mm.origin);
|
|
|
|
mm.groundPlane = m_groundPlane;
|
|
|
|
mm.walking = m_walking;
|
|
|
|
m_groundPlaneNormal.copyTo(mm.groundPlaneNormal);
|
|
|
|
VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal);
|
|
|
|
|
|
|
|
m_Path.UpdatePos(mm.hit_origin);
|
|
|
|
if (!m_Path.NextNode())
|
|
|
|
{
|
|
|
|
if (!m_WallDir)
|
|
|
|
{
|
|
|
|
auto dir = m_Path.CurrentDelta();
|
|
|
|
if (m_Path.NextNode())
|
|
|
|
{
|
|
|
|
dir = m_Path.NextNode()->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1])
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[1];
|
|
|
|
m_WallDir = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[1];
|
|
|
|
m_WallDir = -1;
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (!mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_WallDir = 0;
|
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! (m_Path.NextNode() && m_Path.NextNode()->bAccurate && m_Path.IsSide()) )
|
|
|
|
{
|
|
|
|
if (m_WallDir)
|
|
|
|
{
|
|
|
|
if (m_WallDir < 0)
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
m_WallDir = 0;
|
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
auto dir = m_Path.CurrentDelta();
|
|
|
|
auto pNextNode = m_Path.NextNode();
|
|
|
|
|
|
|
|
if (pNextNode)
|
|
|
|
{
|
|
|
|
dir = pNextNode->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = pNextNode->point[1] - mm.hit_origin[0];
|
|
|
|
vDelta[1] = pNextNode->point[0] - mm.hit_origin[1];
|
|
|
|
|
|
|
|
if (DotProduct2D(dir, vDelta) >= 0)
|
|
|
|
{
|
|
|
|
float fCross = CrossProduct2D(dir, vDelta);
|
|
|
|
if (fCross <= -16)
|
|
|
|
{
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fCross >= 16)
|
|
|
|
{
|
|
|
|
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
if (!m_WallDir)
|
|
|
|
{
|
|
|
|
auto dir = m_Path.CurrentDelta();
|
|
|
|
if (m_Path.NextNode())
|
|
|
|
{
|
|
|
|
dir = m_Path.NextNode()->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1])
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
m_WallDir = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
m_WallDir = -1;
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (!mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_WallDir = 0;
|
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (m_WallDir < 0)
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
m_WallDir = 0;
|
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
|
|
|
|
|
|
|
{
|
|
|
|
auto dir = m_Path.CurrentDelta();
|
|
|
|
auto pNextNode = m_Path.NextNode();
|
|
|
|
|
|
|
|
if (pNextNode)
|
|
|
|
{
|
|
|
|
dir = pNextNode->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = pNextNode->point[1] - mm.hit_origin[0];
|
|
|
|
vDelta[1] = pNextNode->point[0] - mm.hit_origin[1];
|
|
|
|
|
|
|
|
if (vDelta[0] * dir[1] <= vDelta[1] * dir[0])
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
m_WallDir = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
m_WallDir = -1;
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
if (mm.hit_obstacle)
|
|
|
|
{
|
|
|
|
VectorCopy(velocity, mm.velocity);
|
|
|
|
VectorCopy(origin, mm.origin);
|
|
|
|
mm.groundPlane = m_groundPlane;
|
|
|
|
mm.walking = m_walking;
|
|
|
|
VectorCopy(m_groundPlaneNormal, mm.groundPlaneNormal);
|
|
|
|
|
|
|
|
VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal);
|
|
|
|
|
|
|
|
if (m_WallDir == char(-1))
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MovePathGoal
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move on path end(goal).
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::MovePathGoal
|
|
|
|
(
|
|
|
|
float fMoveSpeed
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fTimeToGo, fDeltaSquareLen, fSlowdownSpeed;
|
|
|
|
vec2_t vDelta;
|
|
|
|
|
|
|
|
if (!m_Path.HasCompleteLookahead())
|
|
|
|
{
|
|
|
|
MovePath(fMoveSpeed);
|
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fTimeToGo = m_fPathGoalTime - level.time;
|
|
|
|
|
|
|
|
|
|
|
|
VectorSub2D(origin, m_Path.LastNode()->point, vDelta);
|
|
|
|
|
|
|
|
fDeltaSquareLen = VectorLength2DSquared(vDelta);
|
|
|
|
if (fTimeToGo <= -0.001)
|
|
|
|
{
|
|
|
|
if (fDeltaSquareLen < (Square(fMoveSpeed * Square(0.5))))
|
|
|
|
{
|
|
|
|
fTimeToGo = 0.5;
|
|
|
|
m_fPathGoalTime = level.time + fTimeToGo;
|
|
|
|
if (m_csPathGoalEndAnimScript == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
m_csPathGoalEndAnimScript = STRING_ANIM_IDLE_SCR;
|
|
|
|
}
|
|
|
|
m_bStartPathGoalEndAnim = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MovePath(fMoveSpeed);
|
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fSlowdownSpeed = sqrt(fDeltaSquareLen) * (2 / (fTimeToGo + level.frametime));
|
|
|
|
if (fSlowdownSpeed > fMoveSpeed + 0.001 && fSlowdownSpeed > 0.4 * sv_runspeed->value)
|
|
|
|
{
|
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
StartAnimation(3, m_Anim);
|
|
|
|
MovePath(fMoveSpeed);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MovePath(fSlowdownSpeed);
|
|
|
|
if (level.time >= m_fPathGoalTime)
|
|
|
|
{
|
|
|
|
m_eAnimMode = 1;
|
|
|
|
Com_Printf("m_eAnimMode MovePathGoal \n");
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::Dumb
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Make actor dumb.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::Dumb
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_DISABLE_AI_SCR);
|
|
|
|
ExecuteScript(&e1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PhysicsOn
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Enable physics.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PhysicsOn
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDoPhysics = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PhysicsOn
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Disable PhysicsOff.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PhysicsOff
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDoPhysics = false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetMood
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current mood.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetMood
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csMood);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetMood
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current mood.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetMood
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csMood = ev->GetConstString(1);
|
|
|
|
if (m_csMood > STRING_ALERT)
|
|
|
|
{
|
|
|
|
m_csMood = STRING_BORED;
|
|
|
|
ScriptError("invalid mood - setting to bored");
|
|
|
|
}
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventDamagePuff
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Spawns a puff of 'blood' smoke at the speficied location in the specified direction.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::EventDamagePuff
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector pos = ev->GetVector(1), dir = ev->GetVector(2);
|
|
|
|
gi.SetBroadcastVisible(pos, NULL);
|
|
|
|
//FIXME: macro
|
|
|
|
gi.MSG_StartCGM(7);
|
|
|
|
gi.MSG_WriteCoord(pos.x);
|
|
|
|
gi.MSG_WriteCoord(pos.y);
|
|
|
|
gi.MSG_WriteCoord(pos.z);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.MSG_WriteDir(dir);
|
|
|
|
gi.MSG_WriteBits(0, 1);
|
|
|
|
gi.MSG_EndCGM();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetAngleYawSpeed
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current AngleYawSpeed.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetAngleYawSpeed
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fAngleYawSpeed);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetAngleYawSpeed
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current AngleYawSpeed.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAngleYawSpeed
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float speed = ev->GetFloat(1);
|
|
|
|
if (speed <= 0)
|
|
|
|
{
|
|
|
|
ScriptError("Attempting to set illegal turnspeed %f", speed);
|
|
|
|
}
|
|
|
|
m_fAngleYawSpeed = speed;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetAimTarget
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current weapon's aim tagret.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAimTarget
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
weap->SetAimTarget(ev->GetEntity(1));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ReadyToFire
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if weapon is ready to fire.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ReadyToFire
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
bool ready;
|
|
|
|
|
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ready = weap && weap->ReadyToFire(FIRE_PRIMARY, true);
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(ready);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetSight
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Return current sight (vision distance).
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetSight
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fSight);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetSight
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current sight (vision distance).
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetSight
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fSight = ev->GetFloat(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetHearing
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current hearing distance.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetHearing
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fHearing);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetHearing
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current hearing distance.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetHearing
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fHearing = ev->GetFloat(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetFov
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current fov.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetFov
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fFov);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetFov
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current fov.
|
|
|
|
============
|
2018-09-17 23:50:38 +02:00
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetFov
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float fov = ev->GetFloat(1);
|
|
|
|
if (fov < 0 || fov > 360)
|
|
|
|
{
|
|
|
|
ScriptError("fov must be in the range [0,360]");
|
|
|
|
}
|
|
|
|
m_fFov = fov;
|
|
|
|
m_fFovDot = cos(0.5 * fov * M_PI / 180.0);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearPatrolCurrentNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear current patrol node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearPatrolCurrentNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_patrolCurrentNode)
|
|
|
|
{
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
delete m_patrolCurrentNode;
|
|
|
|
}
|
|
|
|
m_patrolCurrentNode = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::NextPatrolCurrentNode
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Switch to next patrol node.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::NextPatrolCurrentNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_bScriptGoalValid)
|
|
|
|
{
|
|
|
|
if (m_patrolCurrentNode->origin == m_vScriptGoal)
|
|
|
|
{
|
|
|
|
m_bScriptGoalValid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
ClearPatrolCurrentNode();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_patrolCurrentNode = m_patrolCurrentNode->Next();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::SetPatrolCurrentNode
|
|
|
|
|
|
|
|
Set current patrol node.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::SetPatrolCurrentNode
|
|
|
|
(
|
|
|
|
Vector& vec
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPatrolCurrentNode();
|
|
|
|
|
|
|
|
TempWaypoint * twp = new TempWaypoint();
|
|
|
|
|
|
|
|
m_patrolCurrentNode = twp;
|
|
|
|
|
|
|
|
m_patrolCurrentNode->setOrigin(vec);
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetPatrolCurrentNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current patrol node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetPatrolCurrentNode
|
|
|
|
(
|
|
|
|
Listener *l
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPatrolCurrentNode();
|
|
|
|
|
|
|
|
if (l && !l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError("Bad patrol path with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z
|
|
|
|
);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_patrolCurrentNode = (SimpleEntity *)l;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetPatrolPath
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current patrol path.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetPatrolPath
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
SetPatrolCurrentNode(ev->GetListener(1));
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetPatrolPath
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current patrol path.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetPatrolPath
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddListener(m_patrolCurrentNode);
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetPatrolWaitTrigger
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set m_bPatrolWaitTrigger.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetPatrolWaitTrigger
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bPatrolWaitTrigger = ev->GetBoolean(1);
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetPatrolWaitTrigger
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get m_bPatrolWaitTrigger.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetPatrolWaitTrigger
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bPatrolWaitTrigger);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ShowInfo_PatrolCurrentNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Show current patrol node info.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ShowInfo_PatrolCurrentNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_patrolCurrentNode)
|
|
|
|
{
|
|
|
|
Com_Printf("current patrol node: %s\n", m_patrolCurrentNode->targetname.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Com_Printf("no current patrol node\n");
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ShowInfo_AimNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Show current aim node info.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ShowInfo_AimNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_aimNode)
|
|
|
|
{
|
|
|
|
Com_Printf("aim node: %s\n", m_aimNode->targetname.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Com_Printf("no current aim node\n");
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MoveOnPathWithSquad
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move on path with squad.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::MoveOnPathWithSquad
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fDistSquared, fIntervalSquared;
|
|
|
|
vec2_t vMyNormalDir, vDelta, vHisDir;
|
|
|
|
Player *p;
|
|
|
|
|
|
|
|
//FIXMEL: macro
|
|
|
|
if (level.inttime < m_iSquadStandTime + 500 || !PathExists() || PathComplete())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fIntervalSquared = Square(m_fInterval);
|
|
|
|
if (m_iSquadStandTime)
|
|
|
|
{
|
|
|
|
fIntervalSquared *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = (Player *)G_GetEntity(0);
|
|
|
|
|
|
|
|
if (IsTeamMate(p))
|
|
|
|
{
|
|
|
|
VectorSub2D(p->origin, origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
if (fIntervalSquared > fDistSquared && DotProduct2D(vDelta, PathDelta()) > 0)
|
|
|
|
{
|
|
|
|
VectorSub2D(velocity, p->velocity, vMyNormalDir);
|
|
|
|
VectorNormalize2D(vMyNormalDir);
|
|
|
|
if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) < 2304)
|
|
|
|
{
|
|
|
|
m_iSquadStandTime = level.inttime;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Actor *pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer())
|
|
|
|
{
|
|
|
|
if (!pSquadMate->IsSubclassOfActor())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
VectorSub2D(pSquadMate->origin, origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
if (fDistSquared >= fIntervalSquared || DotProduct2D(vDelta, PathDelta()) <= 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (pSquadMate->PathExists() || pSquadMate->PathComplete())
|
|
|
|
{
|
|
|
|
VectorCopy2D(pSquadMate->velocity, vHisDir);
|
|
|
|
if (VectorLength2DSquared(vHisDir) <= 8)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VectorCopy2D(pSquadMate->PathDelta(), vHisDir);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DotProduct2D(PathDelta(), vHisDir) >= 0 && (entnum == pSquadMate->entnum || DotProduct2D(vHisDir, vDelta) >= 0))
|
|
|
|
{
|
|
|
|
m_iSquadStandTime = level.inttime;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MoveToWaypointWithPlayer
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Move to waypoint with player.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::MoveToWaypointWithPlayer
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fIntervalSquared, fDistSquared;
|
|
|
|
vec2_t vMyNormalDir, vDelta, vMyDir;
|
|
|
|
|
|
|
|
if (level.inttime < m_iSquadStandTime + 500)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fIntervalSquared = Square(m_fInterval);
|
|
|
|
if (m_iSquadStandTime)
|
|
|
|
{
|
|
|
|
fIntervalSquared += fIntervalSquared;
|
|
|
|
}
|
|
|
|
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
if (IsTeamMate(p))
|
|
|
|
{
|
|
|
|
vDelta[0] = p->origin[0] - origin[0];
|
|
|
|
vDelta[1] = p->origin[1] - origin[1];
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
|
|
|
|
if (fDistSquared >= fIntervalSquared)
|
|
|
|
{
|
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vMyDir[0] = m_patrolCurrentNode->origin[0] - origin[0];
|
|
|
|
vMyDir[1] = m_patrolCurrentNode->origin[1] - origin[1];
|
|
|
|
if (DotProduct2D(vDelta, vMyDir) < 0)
|
|
|
|
{
|
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vMyNormalDir[0] = velocity[0] - p->velocity[0];
|
|
|
|
vMyNormalDir[1] = velocity[1] - p->velocity[1];
|
|
|
|
VectorNormalize2D(vMyNormalDir);
|
|
|
|
|
|
|
|
if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) > 2304)
|
|
|
|
{
|
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
m_iSquadStandTime = level.inttime;
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PatrolNextNodeExists
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if next patrol node exits.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::PatrolNextNodeExists
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return m_patrolCurrentNode && !( m_patrolCurrentNode->IsSubclassOfTempWaypoint() ) && m_patrolCurrentNode->Next();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdatePatrolCurrentNode
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update current patrol node.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdatePatrolCurrentNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
bool next = false;
|
|
|
|
if (m_patrolCurrentNode)
|
|
|
|
{
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint())
|
|
|
|
{
|
|
|
|
if (fabs(origin[0] - m_patrolCurrentNode->origin[0]) < 16.0
|
|
|
|
&& fabs(origin[1] - m_patrolCurrentNode->origin[1]) < 16.0)
|
|
|
|
{
|
|
|
|
next = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(PathExists() && PathComplete())
|
|
|
|
{
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
next = true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
if (next)
|
|
|
|
{
|
|
|
|
NextPatrolCurrentNode();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::MoveToPatrolCurrentNode
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::MoveToPatrolCurrentNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UpdatePatrolCurrentNode();
|
|
|
|
if (m_patrolCurrentNode && !m_bPatrolWaitTrigger)
|
|
|
|
{
|
|
|
|
Vector delta;
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfWaypoint())
|
|
|
|
{
|
|
|
|
if (MoveToWaypointWithPlayer())
|
|
|
|
{
|
|
|
|
m_bNextForceStart = false;
|
|
|
|
m_eNextAnimMode = 4;
|
|
|
|
m_csNextAnimString = m_csPatrolCurrentAnim;
|
|
|
|
FaceMotion();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Anim_Stand();
|
|
|
|
IdleLook();
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDest(m_patrolCurrentNode->origin);
|
|
|
|
|
|
|
|
if (m_fMoveDoneRadiusSquared == 0.0 || m_patrolCurrentNode->Next())
|
|
|
|
return false;
|
|
|
|
delta = m_patrolCurrentNode->origin - origin;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SimpleActor::SetPath(
|
|
|
|
m_patrolCurrentNode->origin,
|
|
|
|
"Actor::MoveToPatrolCurrentNode",
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
if (!PathExists())
|
|
|
|
{
|
|
|
|
IdleLook();
|
|
|
|
|
|
|
|
Anim_Idle();
|
|
|
|
parm.movefail = qtrue;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (MoveOnPathWithSquad())
|
|
|
|
{
|
|
|
|
if (PatrolNextNodeExists())
|
|
|
|
{
|
|
|
|
m_eNextAnimMode = 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_eNextAnimMode = 3;
|
|
|
|
}
|
|
|
|
m_csNextAnimString = m_csPatrolCurrentAnim;
|
|
|
|
m_bNextForceStart = false;
|
|
|
|
FaceMotion();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Anim_Stand();
|
|
|
|
IdleLook();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_fMoveDoneRadiusSquared == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (PathComplete())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_Path.HasCompleteLookahead() || m_patrolCurrentNode->Next())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
delta = PathDelta();
|
|
|
|
}
|
|
|
|
return m_fMoveDoneRadiusSquared >= delta.lengthXYSquared();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IdleLook();
|
|
|
|
Anim_Idle();
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetAccuracy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current accuracy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAccuracy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
mAccuracy = ev->GetFloat(1) / 100;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventGetAccuracy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get current accuracy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetAccuracy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(mAccuracy * 100);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetMinDistance
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistance = ev->GetFloat(1);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_fMinDistance < 0)
|
|
|
|
{
|
|
|
|
m_fMinDistance = 0;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ Warning: mindist negative, forcing to %g for entity %i, targetname '%s'\n",
|
|
|
|
m_fMinDistance,
|
|
|
|
entnum,
|
|
|
|
targetname.c_str());
|
|
|
|
}
|
|
|
|
m_fMinDistanceSquared = m_fMinDistance * m_fMinDistance;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetMinDistance
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fMinDistance);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetMaxDistance
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_fMaxDistance = ev->GetFloat(1);
|
|
|
|
//FIXME: macro
|
|
|
|
if (m_fMaxDistance < 256)
|
|
|
|
{
|
|
|
|
m_fMaxDistance = 256;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ Warning: maxdist too small, forcing to %g for entity %i, targetname '%s'\n",
|
|
|
|
m_fMaxDistance,
|
|
|
|
entnum,
|
|
|
|
targetname.c_str());
|
|
|
|
}
|
|
|
|
m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetMaxDistance
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fMaxDistance);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetLeash
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fLeash);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetLeash
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_fLeash = ev->GetFloat(1);
|
|
|
|
m_fLeashSquared = Square(m_fLeash);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetInterval
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fInterval);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetInterval
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_fInterval = ev->GetFloat(1);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventDistToEnemy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float dist = 0;
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
Vector distV = origin - m_Enemy->origin;
|
|
|
|
dist = distV.length();
|
|
|
|
}
|
|
|
|
ev->AddFloat(dist);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::Init
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Initialize global actor variables.
|
|
|
|
Called from G_InitGame()
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::Init
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
g_showinfo = gi.Cvar_Get("g_showinfo", "0", 0);
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_THINKS; i++)
|
|
|
|
{
|
|
|
|
GlobalFuncs[i].ThinkState = NULL;
|
|
|
|
GlobalFuncs[i].BeginState = NULL;
|
|
|
|
GlobalFuncs[i].ResumeState = NULL;
|
|
|
|
GlobalFuncs[i].EndState = NULL;
|
|
|
|
GlobalFuncs[i].SuspendState = NULL;
|
|
|
|
GlobalFuncs[i].RestartState = &Actor::DefaultRestart;
|
|
|
|
GlobalFuncs[i].FinishedAnimation = NULL;
|
|
|
|
GlobalFuncs[i].PostShoot = NULL;
|
|
|
|
GlobalFuncs[i].Pain = &Actor::DefaultPain;
|
|
|
|
GlobalFuncs[i].Killed = &Actor::DefaultKilled;
|
|
|
|
GlobalFuncs[i].PassesTransitionConditions = NULL;
|
|
|
|
GlobalFuncs[i].ShowInfo = NULL;
|
|
|
|
GlobalFuncs[i].ReceiveAIEvent = &Actor::DefaultReceiveAIEvent;
|
|
|
|
GlobalFuncs[i].IsState = NULL;
|
|
|
|
GlobalFuncs[i].PathnodeClaimRevoked = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitVoid(&GlobalFuncs[THINK_VOID]);
|
|
|
|
InitTurret(&GlobalFuncs[THINK_TURRET]);
|
|
|
|
InitCover(&GlobalFuncs[THINK_COVER]);
|
|
|
|
InitPatrol(&GlobalFuncs[THINK_PATROL]);
|
|
|
|
InitRunner(&GlobalFuncs[THINK_RUNNER]);
|
|
|
|
InitPain(&GlobalFuncs[THINK_PAIN]);
|
|
|
|
InitKilled(&GlobalFuncs[THINK_KILLED]);
|
|
|
|
InitIdle(&GlobalFuncs[THINK_IDLE]);
|
|
|
|
InitCurious(&GlobalFuncs[THINK_CURIOUS]);
|
|
|
|
InitDisguiseSalute(&GlobalFuncs[THINK_DISGUISE_SALUTE]);
|
|
|
|
InitDisguiseSentry(&GlobalFuncs[THINK_DISGUISE_SENTRY]);
|
|
|
|
InitDisguiseOfficer(&GlobalFuncs[THINK_DISGUISE_OFFICER]);
|
|
|
|
InitDisguiseRover(&GlobalFuncs[THINK_DISGUISE_ROVER]);
|
|
|
|
InitDisguiseNone(&GlobalFuncs[THINK_DISGUISE_NONE]);
|
|
|
|
InitAlarm(&GlobalFuncs[THINK_ALARM]);
|
|
|
|
InitGrenade(&GlobalFuncs[THINK_GRENADE]);
|
|
|
|
InitMachineGunner(&GlobalFuncs[THINK_MACHINEGUNNER]);
|
|
|
|
InitDogIdle(&GlobalFuncs[THINK_DOG_IDLE]);
|
|
|
|
InitDogAttack(&GlobalFuncs[THINK_DOG_ATTACK]);
|
|
|
|
InitDogCurious(&GlobalFuncs[THINK_DOG_CURIOUS]);
|
|
|
|
InitAnim(&GlobalFuncs[THINK_ANIM]);
|
|
|
|
InitAnimCurious(&GlobalFuncs[THINK_ANIM_CURIOUS]);
|
|
|
|
InitAim(&GlobalFuncs[THINK_AIM]);
|
|
|
|
InitBalconyIdle(&GlobalFuncs[THINK_BALCONY_IDLE]);
|
|
|
|
InitBalconyCurious(&GlobalFuncs[THINK_BALCONY_CURIOUS]);
|
|
|
|
InitBalconyAttack(&GlobalFuncs[THINK_BALCONY_ATTACK]);
|
|
|
|
InitBalconyDisguise(&GlobalFuncs[THINK_BALCONY_DISGUISE]);
|
|
|
|
InitBalconyGrenade(&GlobalFuncs[THINK_BALCONY_GRENADE]);
|
|
|
|
InitBalconyPain(&GlobalFuncs[THINK_BALCONY_PAIN]);
|
|
|
|
InitBalconyKilled(&GlobalFuncs[THINK_BALCONY_KILLED]);
|
|
|
|
InitWeaponless(&GlobalFuncs[THINK_WEAPONLESS]);
|
|
|
|
InitNoClip(&GlobalFuncs[THINK_NOCLIP]);
|
|
|
|
InitDead(&GlobalFuncs[THINK_DEAD]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AddWaitTill(STRING_TRIGGER);
|
|
|
|
AddWaitTill(STRING_MOVE);
|
|
|
|
AddWaitTill(STRING_ANIMDONE);
|
|
|
|
AddWaitTill(STRING_VISIBLE);
|
|
|
|
AddWaitTill(STRING_UPPERANIMDONE);
|
|
|
|
AddWaitTill(STRING_SAYDONE);
|
|
|
|
AddWaitTill(STRING_FLAGGEDANIMDONE);
|
|
|
|
AddWaitTill(STRING_DEATH);
|
|
|
|
AddWaitTill(STRING_PAIN);
|
|
|
|
AddWaitTill(STRING_HASENEMY);
|
|
|
|
AddWaitTill(STRING_MOVEDONE);
|
|
|
|
AddWaitTill(STRING_SOUNDDONE);
|
|
|
|
AddWaitTill(STRING_TURNDONE);
|
|
|
|
|
|
|
|
gi.DPrintf("actor waittills registered\n");
|
|
|
|
|
|
|
|
if (developer->integer)
|
|
|
|
{
|
|
|
|
Com_Printf("sizeof(Actor) == %zi\n", sizeof(Actor));
|
|
|
|
//FIXME: magic ??
|
|
|
|
Com_Printf("Magic sizeof actor number: %zd\n", sizeof(Actor));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateEyeOrigin
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update eye position.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateEyeOrigin
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector eyeTag = vec_zero;
|
|
|
|
|
|
|
|
int currLvlTime = level.inttime;
|
|
|
|
int currTime = m_iEyeUpdateTime;
|
2019-06-29 23:43:30 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (currLvlTime > currTime)
|
|
|
|
{
|
|
|
|
|
|
|
|
m_iEyeUpdateTime = NextUpdateTime(currTime, 100);
|
|
|
|
|
|
|
|
GetTag( "eyes bone", &eyeTag, &m_vEyeDir);
|
|
|
|
|
|
|
|
eyeposition = eyeTag - origin;
|
|
|
|
|
|
|
|
m_vEyeDir[2] = 0.0;
|
|
|
|
VectorNormalizeFast(m_vEyeDir);
|
|
|
|
|
|
|
|
if (eyeposition[0] < -10.5)
|
|
|
|
{
|
|
|
|
eyeposition[0] = -10.5;
|
|
|
|
}
|
|
|
|
if (eyeposition[0] > 10.5)
|
|
|
|
eyeposition[0] = 10.5;
|
|
|
|
|
|
|
|
if (eyeposition[1] < -10.5)
|
|
|
|
{
|
|
|
|
eyeposition[1] = -10.5;
|
|
|
|
}
|
|
|
|
if (eyeposition[1] > 10.5)
|
|
|
|
eyeposition[1] = 10.5;
|
|
|
|
|
|
|
|
if (eyeposition[2] < 4.5)
|
|
|
|
{
|
|
|
|
eyeposition[2] = 4.5;
|
|
|
|
}
|
|
|
|
if (eyeposition[2] > 89.5)
|
|
|
|
eyeposition[2] = 89.5;
|
|
|
|
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::RequireThink
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Do I need to think ?
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::RequireThink
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if(G_GetEntity(0))
|
|
|
|
return ( level.inttime < edict->r.lastNetTime + 60000 );
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateEnemyInternal
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Real update enemy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateEnemyInternal
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
for (Sentient *pSent = level.m_HeadSentient[1 - m_Team]; pSent; pSent = pSent->m_NextSentient)
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.AddPotentialEnemy(pSent);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_PotentialEnemies.CheckEnemies(this);
|
|
|
|
|
|
|
|
if (m_Enemy != m_PotentialEnemies.GetCurrentEnemy())
|
|
|
|
SetEnemy(m_PotentialEnemies.GetCurrentEnemy(), false);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fNoticeTimeScale += (level.inttime - m_iEnemyCheckTime) / 10000;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_fNoticeTimeScale > m_fMaxNoticeTimeScale)
|
|
|
|
m_fNoticeTimeScale = m_fMaxNoticeTimeScale;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyCheckTime = level.inttime;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update enemy w.r.t m_iEnemyCheckTime.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateEnemy
|
|
|
|
(
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyCheckTime)
|
|
|
|
UpdateEnemyInternal();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current enemy.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetEnemy
|
|
|
|
(
|
|
|
|
Sentient *pEnemy,
|
|
|
|
bool bForceConfirmed
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (pEnemy == m_Enemy)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
m_Enemy->m_iAttackerCount--;
|
|
|
|
}
|
|
|
|
m_bNewEnemy = m_Enemy == NULL;
|
|
|
|
//delete m_Enemy;
|
|
|
|
|
|
|
|
m_Enemy = pEnemy;
|
|
|
|
|
|
|
|
m_iEnemyChangeTime = level.inttime;
|
|
|
|
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
Event e1(EV_Actor_ShareEnemy);
|
|
|
|
//FIXME: macro
|
|
|
|
PostEvent(e1, 0.75);
|
|
|
|
|
|
|
|
if (m_Enemy->m_bHasDisguise)
|
|
|
|
{
|
|
|
|
if (level.inttime > m_iEnemyVisibleCheckTime)
|
|
|
|
{
|
|
|
|
//this cansee call changes m_bEnemyVisible and m_bEnemyInFOV
|
|
|
|
//FIXME: macro
|
|
|
|
CanSee(m_Enemy, 0, 0.828 * world->farplane_distance, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bEnemyIsDisguised = m_Enemy->m_bHasDisguise && (m_Enemy->m_bIsDisguised || !m_bEnemyVisible);
|
|
|
|
|
|
|
|
SetEnemyPos(m_Enemy->origin);
|
|
|
|
|
|
|
|
m_Enemy->m_iAttackerCount++;
|
|
|
|
|
|
|
|
if (bForceConfirmed)
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, m_Enemy);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetEnemyPos
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update stored enemy position information.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetEnemyPos
|
|
|
|
(
|
|
|
|
Vector vPos
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_vLastEnemyPos != vPos)
|
|
|
|
{
|
|
|
|
m_iLastEnemyPosChangeTime = level.inttime;
|
|
|
|
m_vLastEnemyPos = vPos;
|
|
|
|
mTargetPos = m_vLastEnemyPos;
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
mTargetPos += m_Enemy->eyeposition;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mTargetPos.z += 88;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mTargetPos.z - EyePosition().z < 128)
|
|
|
|
{
|
|
|
|
mTargetPos.z -= 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
static bool UnknownAnim(const char *name, dtiki_t *tiki)
|
|
|
|
{
|
|
|
|
ScriptException::next_bIsForAnim = true;
|
|
|
|
ScriptError("unknown animation '%s' in '%s'", name, tiki->a->name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set animation event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//"anim slot weight flagged"
|
|
|
|
int numArgs = ev->NumArgs(), slot = 0, animnum;
|
|
|
|
float weight = 1;
|
|
|
|
const_str anim, flagVal;
|
|
|
|
qboolean flagged = qfalse;
|
|
|
|
|
|
|
|
//FIXME: better notation, but this works for now.
|
|
|
|
if (numArgs < 1 || numArgs > 4)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
else if (numArgs == 1)
|
|
|
|
{
|
|
|
|
anim = ev->GetConstString(1);
|
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (numArgs == 2)
|
|
|
|
{
|
|
|
|
anim = ev->GetConstString(1);
|
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
slot = ev->GetInteger(2);
|
|
|
|
if (slot > 2)
|
|
|
|
{
|
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (numArgs == 3)
|
|
|
|
{
|
|
|
|
weight = ev->GetFloat(3);
|
|
|
|
if (weight < 0)
|
|
|
|
{
|
|
|
|
ScriptError("Negative anim weight not allowed");
|
|
|
|
}
|
|
|
|
if (weight != 0)
|
|
|
|
{
|
|
|
|
slot = ev->GetInteger(2);
|
|
|
|
if (slot > 2)
|
|
|
|
{
|
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
anim = ev->GetConstString(1);
|
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (numArgs == 4)
|
|
|
|
{
|
|
|
|
flagVal = ev->GetConstString(4);
|
|
|
|
flagged = qtrue;
|
|
|
|
if (flagVal != STRING_FLAGGED)
|
|
|
|
{
|
|
|
|
ScriptError("unknown keyword '%s', expected 'flagged'", Director.GetString(flagVal).c_str());
|
|
|
|
}
|
|
|
|
weight = ev->GetFloat(3);
|
|
|
|
if (weight < 0)
|
|
|
|
{
|
|
|
|
ScriptError("Negative anim weight not allowed");
|
|
|
|
}
|
|
|
|
if (weight != 0)
|
|
|
|
{
|
|
|
|
slot = ev->GetInteger(2);
|
|
|
|
if (slot > 2)
|
|
|
|
{
|
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
anim = ev->GetConstString(1);
|
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!slot)
|
|
|
|
{
|
|
|
|
flagged = qtrue;
|
|
|
|
}
|
|
|
|
if (flagged)
|
|
|
|
{
|
|
|
|
parm.motionfail = qtrue;
|
|
|
|
}
|
|
|
|
if (!m_bLevelMotionAnim)
|
|
|
|
{
|
|
|
|
if (slot)
|
|
|
|
{
|
|
|
|
m_weightType[GetMotionSlot(slot)] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
}
|
|
|
|
StartMotionAnimSlot(slot, animnum, weight);
|
|
|
|
if (flagged)
|
|
|
|
{
|
|
|
|
m_iMotionSlot = GetMotionSlot(slot);
|
|
|
|
parm.motionfail = qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventEndActionAnim
|
|
|
|
|
|
|
|
End action animation.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::EventEndActionAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.upperfail = qtrue;
|
|
|
|
if (!m_bLevelActionAnim)
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
parm.upperfail = qfalse;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetMotionAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set motion animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetMotionAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.DPrintf("Actor::EventSetMotionAnim\n");
|
|
|
|
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
str animstr = Director.GetString(anim);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, animstr.c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(animstr.c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
gi.DPrintf("Actor::EventSetMotionAnim %s %d\n", animstr.c_str(), animnum);
|
|
|
|
parm.motionfail = qtrue;
|
|
|
|
|
|
|
|
if (!m_bLevelMotionAnim)
|
|
|
|
{
|
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
StartMotionAnimSlot(0, animnum, 1.0);
|
|
|
|
m_iMotionSlot = GetMotionSlot(0);
|
|
|
|
parm.motionfail = qfalse;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetAimMotionAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set aim motion animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAimMotionAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int anim_crouch, anim_stand, anim_high;
|
|
|
|
const_str name;
|
|
|
|
if (ev->NumArgs() != 3)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: maybe inline func ?
|
|
|
|
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
anim_crouch = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
|
|
|
if (anim_crouch == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(2);
|
|
|
|
anim_stand = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
|
|
|
if (anim_stand == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(3);
|
|
|
|
anim_high = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
|
|
|
if (anim_high == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parm.motionfail = qtrue;
|
|
|
|
|
|
|
|
if (!m_bLevelMotionAnim)
|
|
|
|
{
|
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
UpdateAimMotion();
|
|
|
|
StartAimMotionAnimSlot(0, anim_crouch);
|
|
|
|
StartAimMotionAnimSlot(1, anim_stand);
|
|
|
|
StartAimMotionAnimSlot(2, anim_high);
|
|
|
|
m_iMotionSlot = GetMotionSlot(1);
|
|
|
|
parm.motionfail = qfalse;
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetActionAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set action animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetActionAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() != 3)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fAimLimit_down = ev->GetFloat(2);
|
|
|
|
if (m_fAimLimit_down > 0)
|
|
|
|
{
|
|
|
|
m_fAimLimit_down = -0.001f;
|
|
|
|
ScriptError("Positive lower_limit not allowed");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fAimLimit_up = ev->GetFloat(3);
|
|
|
|
if (m_fAimLimit_up <= 0)
|
|
|
|
{
|
|
|
|
m_fAimLimit_up = 0.001f;
|
|
|
|
ScriptError("Negative upper_limit not allowed");
|
|
|
|
}
|
|
|
|
|
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
const_str anim2 = ev->GetConstString(2);
|
|
|
|
int animnum2 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim2));
|
|
|
|
if (animnum2 == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim2).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
const_str anim3 = ev->GetConstString(3);
|
|
|
|
int animnum3 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim3));
|
|
|
|
if (animnum3 == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim3).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
parm.upperfail = qtrue;
|
|
|
|
if (!m_bLevelActionAnim)
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
m_bAimAnimSet = true;
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
UpdateAim();
|
|
|
|
|
|
|
|
StartAimAnimSlot(0, animnum);
|
|
|
|
StartAimAnimSlot(1, anim2);
|
|
|
|
StartAimAnimSlot(2, anim3);
|
|
|
|
m_iActionSlot = GetActionSlot(0);
|
|
|
|
parm.upperfail = qfalse;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventUpperAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set upper body.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventUpperAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ev->NumArgs())
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csUpperAnim = anim;
|
|
|
|
}
|
|
|
|
else if (m_bLevelActionAnim)
|
|
|
|
{
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetUpperAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set upper body animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetUpperAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.upperfail = qtrue;
|
|
|
|
if (!m_bLevelActionAnim)
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
m_iActionSlot = SimpleActor::GetActionSlot(0);
|
|
|
|
parm.upperfail = qfalse;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SoundSayAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if animation not found.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::SoundSayAnim
|
|
|
|
(
|
|
|
|
const_str name,
|
|
|
|
byte bLevelSayAnim
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
m_iSaySlot = -2;
|
|
|
|
m_bLevelSayAnim = bLevelSayAnim;
|
|
|
|
|
|
|
|
Com_Printf(
|
|
|
|
"Couldn't find animation '%s' in '%s' - trying sound alias instead.\n",
|
|
|
|
Director.GetString(name).c_str(),
|
|
|
|
edict->tiki->a->name);
|
|
|
|
|
|
|
|
Sound(Director.GetString(name), 0, 0, 0, NULL, 0, 1, 1, -1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventIdleSayAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play idle say dialogue.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventIdleSayAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
if (ev->NumArgs())
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
|
|
|
if (m_ThinkState <= THINKSTATE_ATTACK || IsGrenadeState(m_ThinkState))
|
|
|
|
{
|
|
|
|
m_csSayAnim = name;
|
|
|
|
//FIXME: macro
|
|
|
|
m_bNextLevelSayAnim = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!SoundSayAnim(name, 1) )
|
|
|
|
{
|
|
|
|
m_csSayAnim = name;
|
|
|
|
//FIXME: macro
|
|
|
|
m_bNextLevelSayAnim = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_bLevelSayAnim == 1)
|
|
|
|
{
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSayAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Play idle dialogue.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSayAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
if (ev->NumArgs())
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
|
|
|
if (m_ThinkState <= THINKSTATE_KILLED || !SoundSayAnim(name, 2))
|
|
|
|
{
|
|
|
|
m_csSayAnim = name;
|
|
|
|
//FIXME: macro
|
|
|
|
m_bNextLevelSayAnim = 2;
|
|
|
|
gi.DPrintf("Actor::EventSayAnim: 1 %s\n", targetname.c_str());
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::EventSayAnim: 2 %s\n", targetname.c_str());
|
|
|
|
}
|
|
|
|
else if (m_bLevelSayAnim == 1)
|
|
|
|
{
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
gi.DPrintf("Actor::EventSayAnim: 3 %s\n", targetname.c_str());
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::EventSayAnim: 4 %s\n", targetname.c_str());
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventSetSayAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set say animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetSayAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
str sName;
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_bLevelSayAnim == 0)
|
|
|
|
{
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
|
|
|
parm.sayfail = qtrue;
|
|
|
|
sName = Director.GetString(name);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, sName.c_str());
|
|
|
|
|
|
|
|
Com_Printf("EventSetSayAnim sName: %s, animnum: %d, mVoiceType: %d\n", sName.c_str(), animnum, mVoiceType);
|
|
|
|
if (!SoundSayAnim(name, m_bLevelSayAnim))
|
|
|
|
{
|
|
|
|
int flags = gi.Anim_FlagsSkel(edict->tiki, animnum);
|
|
|
|
if (flags & TAF_HASUPPER)
|
|
|
|
{
|
|
|
|
if (m_bLevelActionAnim)
|
|
|
|
{
|
|
|
|
if (!m_bSayAnimSet)
|
|
|
|
{
|
|
|
|
m_iSaySlot = m_iActionSlot;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (flags & TAF_HASDELTA)
|
|
|
|
{
|
|
|
|
if (m_bLevelMotionAnim)
|
|
|
|
{
|
|
|
|
if (!m_bSayAnimSet)
|
|
|
|
{
|
|
|
|
m_iSaySlot = m_iMotionSlot;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ChangeActionAnim();
|
|
|
|
ChangeMotionAnim();
|
|
|
|
StartMotionAnimSlot(0, animnum, 1.0);
|
|
|
|
|
|
|
|
m_iMotionSlot = m_iActionSlot = GetMotionSlot(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
m_iActionSlot = GetActionSlot(0);
|
|
|
|
}
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
m_iSaySlot = m_iActionSlot;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
StartSayAnimSlot(animnum);
|
|
|
|
m_iSaySlot = GetSaySlot();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
parm.sayfail = qfalse;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ChangeAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change current animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
void Actor::ChangeAnim
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
bool v3; // zf
|
|
|
|
|
|
|
|
if (m_pAnimThread)
|
|
|
|
{
|
|
|
|
if (g_scripttrace->integer)
|
|
|
|
{
|
|
|
|
if (m_pAnimThread->CanScriptTracePrint())
|
|
|
|
Com_Printf("--- Change Anim\n");
|
|
|
|
}
|
|
|
|
m_pAnimThread->AbortRegistration(
|
|
|
|
STRING_EMPTY,
|
|
|
|
this);
|
|
|
|
ScriptClass * sc = m_pAnimThread->GetScriptClass();
|
|
|
|
if (sc)
|
|
|
|
{
|
|
|
|
delete sc;
|
|
|
|
}
|
|
|
|
Com_Printf("ChangeAnim: m_pAnimThread aborted\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ThinkState != 4) // THINKSTATE_ATTACK
|
|
|
|
{
|
|
|
|
if (m_ThinkState <= 4) // THINKSTATE_ATTACK
|
|
|
|
{
|
|
|
|
if (m_ThinkState >= 2) // THINKSTATE_PAIN
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
v3 = m_bSayAnimSet == 0;
|
|
|
|
LABEL_13:
|
|
|
|
if (v3)
|
|
|
|
goto LABEL_14;
|
|
|
|
goto LABEL_20;
|
|
|
|
}
|
|
|
|
goto LABEL_21;
|
|
|
|
}
|
|
|
|
if (m_ThinkState != 7) // m_ThinkState != THINKSTATE_GRENADE
|
|
|
|
{
|
|
|
|
LABEL_21:
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
{
|
|
|
|
if (!m_bLevelMotionAnim)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
}
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
{
|
|
|
|
if (!m_bLevelActionAnim)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
}
|
|
|
|
if (m_bSayAnimSet && !m_bLevelSayAnim)
|
|
|
|
{
|
|
|
|
LABEL_20:
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
goto LABEL_14;
|
|
|
|
}
|
|
|
|
goto LABEL_14;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet)
|
|
|
|
{
|
|
|
|
v3 = m_bLevelSayAnim == 2;
|
|
|
|
goto LABEL_13;
|
|
|
|
}
|
|
|
|
LABEL_14:
|
|
|
|
m_fCrossblendTime = 0.5;
|
|
|
|
m_pAnimThread = m_Anim.Create(this);
|
|
|
|
if (m_pAnimThread)
|
|
|
|
{
|
|
|
|
if (g_scripttrace->integer)
|
|
|
|
{
|
|
|
|
if (m_pAnimThread->CanScriptTracePrint())
|
|
|
|
Com_Printf("+++ Change Anim\n");
|
|
|
|
}
|
|
|
|
m_pAnimThread->Register(STRING_EMPTY, this);
|
|
|
|
|
|
|
|
m_pAnimThread->StartTiming();
|
|
|
|
Com_Printf("ChangeAnim: m_pAnimThread started\n");
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
void Actor::ChangeAnim
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_pAnimThread)
|
|
|
|
{
|
|
|
|
if (g_scripttrace->integer && m_pAnimThread->CanScriptTracePrint())
|
|
|
|
{
|
|
|
|
Com_Printf("--- Change Anim\n");
|
|
|
|
}
|
|
|
|
m_pAnimThread->AbortRegistration(STRING_EMPTY, this);
|
|
|
|
ScriptClass * sc = m_pAnimThread->GetScriptClass();
|
|
|
|
if (sc)
|
|
|
|
{
|
|
|
|
delete sc;
|
|
|
|
}
|
|
|
|
Com_Printf("ChangeAnim: m_pAnimThread aborted\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ThinkState != THINKSTATE_ATTACK)
|
|
|
|
{
|
|
|
|
if (m_ThinkState > THINKSTATE_ATTACK)
|
|
|
|
{
|
|
|
|
if (m_ThinkState != THINKSTATE_GRENADE)
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet && !m_bLevelMotionAnim)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet && !m_bLevelActionAnim)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet && !m_bLevelSayAnim)
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet && m_bLevelSayAnim != 2)
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_ThinkState < THINKSTATE_PAIN)
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet && !m_bLevelMotionAnim)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet && !m_bLevelActionAnim)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet && !m_bLevelSayAnim)
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet)
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_bMotionAnimSet)
|
|
|
|
AnimFinished(m_iMotionSlot, true);
|
|
|
|
if (m_bActionAnimSet)
|
|
|
|
AnimFinished(m_iActionSlot, true);
|
|
|
|
if (m_bSayAnimSet && m_bLevelSayAnim != 2)
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
m_fCrossblendTime = 0.5;
|
|
|
|
|
|
|
|
m_pAnimThread = m_Anim.Create(this);
|
|
|
|
|
|
|
|
if (m_pAnimThread)
|
|
|
|
{
|
|
|
|
if (g_scripttrace->integer)
|
|
|
|
{
|
|
|
|
if (m_pAnimThread->CanScriptTracePrint())
|
|
|
|
Com_Printf("+++ Change Anim\n");
|
|
|
|
}
|
|
|
|
m_pAnimThread->Register(STRING_EMPTY, this);
|
|
|
|
|
|
|
|
m_pAnimThread->StartTiming();
|
|
|
|
Com_Printf("ChangeAnim: m_pAnimThread started\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateSayAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update say animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateSayAnim
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 1\n");
|
|
|
|
|
|
|
|
if (m_ThinkState > THINKSTATE_KILLED)
|
|
|
|
{
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 2\n");
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csSayAnim).c_str());
|
|
|
|
if (animnum == -1)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 3\n");
|
|
|
|
|
|
|
|
int flags = gi.Anim_FlagsSkel(edict->tiki, animnum);
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
if (flags & 256)
|
|
|
|
{
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 4\n");
|
|
|
|
if ( !IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState) )
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
if (flags & ANIM_NOACTION)
|
|
|
|
{
|
|
|
|
ChangeMotionAnim();
|
|
|
|
|
|
|
|
StartMotionAnimSlot(0, animnum, 1);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
|
|
|
m_bLevelMotionAnim = true;
|
|
|
|
|
|
|
|
m_iMotionSlot = m_iActionSlot = GetMotionSlot(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
|
|
|
|
|
|
|
m_iActionSlot = GetActionSlot(0);
|
|
|
|
}
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
m_bLevelSayAnim = m_bNextLevelSayAnim;
|
|
|
|
m_bNextLevelSayAnim = 0;
|
|
|
|
m_iSaySlot = m_iActionSlot;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 4\n");
|
|
|
|
}
|
|
|
|
else if (m_bNextLevelSayAnim == 2 || (!IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState)) )
|
|
|
|
{
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 6\n");
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
StartSayAnimSlot(animnum);
|
|
|
|
m_bLevelSayAnim = m_bNextLevelSayAnim;
|
|
|
|
m_bNextLevelSayAnim = 0;
|
|
|
|
m_iSaySlot = GetSaySlot();
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 7\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_bSayAnimSet)
|
|
|
|
{
|
|
|
|
Unregister(STRING_SAYDONE);
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 8\n");
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateUpperAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update upper animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateUpperAnim
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csUpperAnim).c_str());
|
|
|
|
if (animnum != -1)
|
|
|
|
{
|
|
|
|
if (IsAttackState(m_ThinkState) || IsGrenadeState(m_ThinkState) || IsKilledState(m_ThinkState) || IsPainState(m_ThinkState))
|
|
|
|
{
|
|
|
|
if (!m_bActionAnimSet)
|
|
|
|
{
|
|
|
|
Unregister(STRING_UPPERANIMDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChangeActionAnim();
|
|
|
|
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
|
|
|
m_iActionSlot = SimpleActor::GetActionSlot(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateAnim
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Update animation.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateAnim
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_bAnimating = true;
|
|
|
|
SimpleActor::UpdateAim();
|
|
|
|
if (SimpleActor::UpdateSelectedAnimation())
|
|
|
|
{
|
|
|
|
Com_Printf("ChangeAnim\n");
|
|
|
|
ChangeAnim();
|
|
|
|
}
|
|
|
|
Director.Unpause();
|
|
|
|
Director.Pause();
|
|
|
|
|
|
|
|
if (m_csSayAnim != STRING_EMPTY)
|
|
|
|
{
|
|
|
|
UpdateSayAnim();
|
|
|
|
m_csSayAnim = STRING_EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_csUpperAnim != STRING_EMPTY)
|
|
|
|
{
|
|
|
|
UpdateUpperAnim();
|
|
|
|
m_csUpperAnim = STRING_EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_bSayAnimSet && !m_bDog)
|
|
|
|
{
|
|
|
|
SimpleActor::UpdateEmotion();
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
for (int slot = 0; slot < 14; slot++)
|
|
|
|
{
|
|
|
|
|
|
|
|
//FIXME: better notation
|
|
|
|
if (!((m_bUpdateAnimDoneFlags >> slot) & 1) )
|
|
|
|
{
|
|
|
|
SimpleActor::UpdateAnimSlot(slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float fAnimTime, fAnimWeight, total_weight = 0, time = 0;
|
|
|
|
for (int slot = 0; slot < 14; slot++)
|
|
|
|
{
|
|
|
|
if ((m_weightType[slot] == 1 || m_weightType[slot] == 4) && animFlags[slot] & ANIM_LOOP)
|
|
|
|
{
|
|
|
|
UseSyncTime(slot, 1);
|
|
|
|
fAnimTime = AnimTime(slot);
|
|
|
|
fAnimWeight = edict->s.frameInfo[slot].weight;
|
|
|
|
time += fAnimTime * fAnimWeight;
|
|
|
|
if (std::isinf(time))
|
|
|
|
{
|
|
|
|
Com_Printf("ent %i, targetname '%s', anim '%s', slot %i, fAnimTime %f, fAnimWeight %f\n",
|
|
|
|
entnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
AnimName(slot),
|
|
|
|
slot,
|
|
|
|
fAnimTime,
|
|
|
|
fAnimWeight);
|
|
|
|
}
|
|
|
|
total_weight += fAnimWeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UseSyncTime(slot, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (total_weight != 0)
|
|
|
|
{
|
|
|
|
SetSyncRate(time / total_weight);
|
|
|
|
}
|
|
|
|
|
|
|
|
PostAnimate();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::Think
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Think function for actor.
|
|
|
|
Calls think function related to the current thinkstate.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::Think
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int v1, v2, v3, tempHistory,ohIndex;
|
|
|
|
m_bAnimating = false;
|
|
|
|
if (g_ai->integer
|
|
|
|
&& m_bDoAI
|
|
|
|
&& edict->tiki)
|
|
|
|
{
|
|
|
|
//gi.DPrintf("Actor::Think 1\n");
|
|
|
|
Director.iPaused++;
|
|
|
|
|
|
|
|
v1 = level.inttime;
|
|
|
|
v2 = v1 / 125;
|
|
|
|
v3 = v1 / 125;
|
|
|
|
if (v1 / 125 < 0)
|
|
|
|
v3 = v2 + 3;
|
|
|
|
tempHistory = v2 - (v3 & 0xFFFFFFFC);
|
|
|
|
|
|
|
|
if (m_iCurrentHistory != tempHistory)
|
|
|
|
{
|
|
|
|
m_iCurrentHistory = tempHistory;
|
|
|
|
ohIndex = tempHistory - 1;
|
|
|
|
if (ohIndex < 0)
|
|
|
|
{
|
|
|
|
ohIndex = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy2D(origin, m_vOriginHistory[ohIndex]);
|
|
|
|
}
|
|
|
|
if (m_bNoPlayerCollision)
|
|
|
|
{
|
|
|
|
Entity *ent = G_GetEntity(0);
|
|
|
|
if (!IsTouching(ent))
|
|
|
|
{
|
|
|
|
Com_Printf("(entnum %d, radnum %d) is going solid after not getting stuck in the player\n", entnum, radnum);
|
|
|
|
setSolidType(SOLID_BBOX);
|
|
|
|
m_bNoPlayerCollision = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//gi.DPrintf("Actor::Think 2\n");
|
|
|
|
m_eNextAnimMode = -1;
|
|
|
|
FixAIParameters();
|
|
|
|
UpdateEnableEnemy();
|
|
|
|
|
|
|
|
if (m_pTetherEnt)
|
|
|
|
{
|
|
|
|
m_vHome = m_pTetherEnt->origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
//gi.DPrintf("Actor::Think 3\n");
|
|
|
|
if (m_bBecomeRunner)
|
|
|
|
{
|
|
|
|
parm.movefail = false;
|
|
|
|
if (m_ThinkMap[THINKSTATE_IDLE] != THINK_RUNNER && m_ThinkMap[THINKSTATE_IDLE] != THINK_PATROL)
|
|
|
|
{
|
|
|
|
parm.movefail = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_bDirtyThinkState)
|
|
|
|
{
|
|
|
|
m_bDirtyThinkState = false;
|
|
|
|
ThinkStateTransitions();
|
|
|
|
}
|
|
|
|
|
|
|
|
//gi.DPrintf("Actor::Think 4\n");
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
|
|
|
if (func->ThinkState)
|
|
|
|
(this->*func->ThinkState)();
|
|
|
|
|
|
|
|
m_bNeedReload = false;
|
|
|
|
mbBreakSpecialAttack = false;
|
|
|
|
Director.Unpause();
|
|
|
|
|
|
|
|
//gi.DPrintf("Actor::Think 5: entnum %d, classname: %s\n", entnum, G_GetEntity(0) ? G_GetEntity(0)->getClassname() : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::CheckUnregister
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bBecomeRunner = false;
|
|
|
|
if (parm.movefail)
|
|
|
|
{
|
|
|
|
parm.movedone = false;
|
|
|
|
Unregister(STRING_MOVEDONE);
|
|
|
|
}
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
Unregister(STRING_HASENEMY);
|
|
|
|
}
|
|
|
|
if (m_bEnemyVisible)
|
|
|
|
{
|
|
|
|
Unregister(STRING_VISIBLE);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PostThink
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Called after think is finished.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::PostThink
|
|
|
|
(
|
|
|
|
bool bDontFaceWall
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
CheckUnregister();
|
|
|
|
if (bDontFaceWall)
|
|
|
|
{
|
|
|
|
if (!m_pTurnEntity || m_ThinkState != THINKSTATE_IDLE)
|
|
|
|
{
|
|
|
|
DontFaceWall();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UpdateAngles();
|
|
|
|
UpdateAnim();
|
|
|
|
DoMove();
|
|
|
|
//gi.DPrintf("Actor::PostThink 1\n");
|
|
|
|
UpdateBoneControllers();
|
|
|
|
//gi.DPrintf("Actor::PostThink 2\n");
|
|
|
|
UpdateFootsteps();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::AnimFinished
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::AnimFinished
|
|
|
|
(
|
|
|
|
int slot,
|
|
|
|
bool stop
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (stop && slot >= 0)
|
|
|
|
animFlags[slot] |= ANIM_NOACTION;
|
|
|
|
if (slot == m_iMotionSlot)
|
|
|
|
{
|
|
|
|
if (stop)
|
|
|
|
{
|
|
|
|
m_bLevelMotionAnim = false;
|
|
|
|
m_iMotionSlot = -1;
|
|
|
|
}
|
|
|
|
MPrintf("flagged anim finished slot %d\n", slot);
|
|
|
|
Unregister(STRING_FLAGGEDANIMDONE);
|
|
|
|
}
|
|
|
|
if (slot == m_iActionSlot)
|
|
|
|
{
|
|
|
|
if (stop)
|
|
|
|
ChangeActionAnim();
|
|
|
|
if (m_csUpperAnim == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
MPrintf("upper anim finished slot %d\n", slot);
|
|
|
|
Unregister(STRING_UPPERANIMDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (slot == m_iSaySlot)
|
|
|
|
{
|
|
|
|
if (stop)
|
|
|
|
ChangeSayAnim();
|
|
|
|
if (m_csSayAnim == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
MPrintf("say anim finished slot %d\n", slot);
|
|
|
|
//gi.DPrintf("unregister STRING_SAYDONE\n");
|
|
|
|
Unregister(STRING_SAYDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (slot == GetSaySlot() && stop)
|
|
|
|
{
|
|
|
|
ChangeSayAnim();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::AnimFinished
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::AnimFinished
|
|
|
|
(
|
|
|
|
int slot
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
animFlags[slot] &= ~ANIM_FINISHED;
|
|
|
|
AnimFinished(slot, ((animFlags[slot] & ANIM_LOOP) != ANIM_LOOP));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetThink
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Modifies think num of current thinkstate inside m_ThinkMap.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetThink
|
|
|
|
(
|
|
|
|
eThinkState state,
|
|
|
|
eThinkNum think
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_ThinkMap[state] = think;
|
|
|
|
if (m_ThinkState == state)
|
|
|
|
m_bDirtyThinkState = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetThink
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set think to idle.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetThinkIdle
|
|
|
|
(
|
|
|
|
eThinkNum think_idle
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
eThinkNum think_curious;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
switch (think_idle)
|
|
|
|
{
|
|
|
|
case THINK_PATROL:
|
|
|
|
case THINK_RUNNER:
|
|
|
|
m_bBecomeRunner = true;
|
|
|
|
think_curious = THINK_CURIOUS;
|
|
|
|
break;
|
|
|
|
case THINK_MACHINEGUNNER:
|
|
|
|
think_curious = THINK_MACHINEGUNNER;
|
|
|
|
break;
|
|
|
|
case THINK_DOG_IDLE:
|
|
|
|
think_curious = THINK_DOG_CURIOUS;
|
|
|
|
SetThink(THINKSTATE_GRENADE, think_curious);
|
|
|
|
break;
|
|
|
|
case THINK_ANIM:
|
|
|
|
think_curious = THINK_ANIM_CURIOUS;
|
|
|
|
break;
|
|
|
|
case THINK_BALCONY_IDLE:
|
|
|
|
think_curious = THINK_BALCONY_CURIOUS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
think_curious = THINK_CURIOUS;
|
|
|
|
break;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
SetThink(THINKSTATE_IDLE, think_idle);
|
|
|
|
|
|
|
|
SetThink(THINKSTATE_CURIOUS, think_curious);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GetThinkType
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Get think for csName.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
int Actor::GetThinkType
|
|
|
|
(
|
|
|
|
const_str csName
|
|
|
|
)
|
2019-06-29 23:43:30 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int result = 0;
|
|
|
|
while (m_csThinkNames[result] != csName)
|
|
|
|
{
|
|
|
|
if (++result > NUM_THINKS - 1)
|
|
|
|
{
|
|
|
|
ScriptError("unknown think type '%s'", Director.GetString(csName).c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
2019-06-29 23:43:30 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetThinkState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set thinkstate.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetThinkState
|
|
|
|
(
|
|
|
|
eThinkState state,
|
|
|
|
eThinkLevel level
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (IsAttackState(state))
|
|
|
|
{
|
|
|
|
m_csIdleMood = STRING_NERVOUS;
|
|
|
|
if (m_ThinkMap[THINKSTATE_ATTACK] != THINK_ALARM && m_ThinkMap[THINKSTATE_ATTACK] != THINK_WEAPONLESS && m_ThinkMap[THINKSTATE_ATTACK] != THINK_DOG_ATTACK && !GetWeapon(WEAPON_MAIN))
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): forcing weaponless attack state.\n"
|
|
|
|
"^~^~^ Level designers should specify 'type_attack weaponless' for this guy.\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str());
|
|
|
|
SetThink(THINKSTATE_ATTACK, THINK_WEAPONLESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ThinkStates[level] = state;
|
|
|
|
|
|
|
|
if (level >= m_ThinkLevel)
|
|
|
|
{
|
|
|
|
m_bDirtyThinkState = true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EndCurrentThinkState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
End current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EndCurrentThinkState
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkState(THINKSTATE_VOID, m_ThinkLevel);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ClearThinkStates
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Clear all thinkstates.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ClearThinkStates
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
for (int i = 0; i <= NUM_THINKLEVELS -1; i++)
|
|
|
|
{
|
|
|
|
SetThinkState(THINKSTATE_VOID, (eThinkLevel)i);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAlarmNode
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Listener *l = ev->GetListener(1);
|
|
|
|
if (l)
|
|
|
|
{
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo))
|
|
|
|
{
|
|
|
|
ScriptError("Alarm node must be an entity");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_AlarmNode = (SimpleEntity *)l;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetAlarmNode
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddListener(m_AlarmNode);
|
|
|
|
}
|
2019-07-01 20:17:46 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAlarmThread
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (ev->IsFromScript())
|
|
|
|
{
|
|
|
|
m_AlarmThread.SetThread(ev->GetValue());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
m_AlarmThread.Set(ev->GetString(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetAlarmThread
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
m_AlarmThread.GetScriptValue(&ev->GetValue());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetSoundAwareness
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fSoundAwareness = ev->GetFloat(1);
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetSoundAwareness
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fSoundAwareness);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetGrenadeAwareness
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_fGrenadeAwareness = ev->GetFloat(1);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetGrenadeAwareness
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fGrenadeAwareness);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetTypeIdle
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeIdle %s : %d\n", ev->GetString(1).c_str(), think);
|
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_IDLE))
|
|
|
|
{
|
|
|
|
SetThinkIdle(THINK_IDLE);
|
|
|
|
ScriptError("Invalid idle think '%s'", Director.GetString(m_csThinkNames[think]).c_str());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(think);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetTypeIdle
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetTypeAttack
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeAttack %s : %d\n", ev->GetString(1).c_str(), think);
|
|
|
|
//check if the wanted think is an attack one.
|
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_ATTACK))
|
|
|
|
{
|
|
|
|
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Invalid attack think '%s'", Director.GetString(m_csThinkNames[think]).c_str());
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_ATTACK, think);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetTypeAttack
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetTypeDisguise
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeDisguise %s : %d\n", ev->GetString(1).c_str(), think);
|
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_DISGUISE))
|
|
|
|
{
|
|
|
|
SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Invalid disguise think '%s'", Director.GetString(m_csThinkNames[think]).c_str());
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_DISGUISE, think);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetDisguiseAcceptThread
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ev->IsFromScript())
|
|
|
|
{
|
|
|
|
m_DisguiseAcceptThread.SetThread(ev->GetValue());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_DisguiseAcceptThread.Set(ev->GetString(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetDisguiseAcceptThread
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_DisguiseAcceptThread.GetScriptValue(&ev->GetValue());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetTypeDisguise
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_DISGUISE]]);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetDisguiseLevel
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_iDisguiseLevel = ev->GetInteger(1);
|
|
|
|
if (m_iDisguiseLevel -1 > 1)
|
|
|
|
{
|
|
|
|
m_iDisguiseLevel = 1;
|
|
|
|
ScriptError("bad disguise level %d for %s, setting to 1\n", m_iDisguiseLevel, targetname.c_str());
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetDisguiseLevel
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddInteger(m_iDisguiseLevel);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetTypeGrenade
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeGrenade %s : %d\n", ev->GetString(1).c_str(), think);
|
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_GRENADE))
|
|
|
|
{
|
|
|
|
SetThink(THINKSTATE_GRENADE, THINK_GRENADE);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Invalid grenade think '%s'", Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]).c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
SetThink(THINKSTATE_GRENADE, think);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetTypeGrenade
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::InitThinkStates
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Initialize think related stuff.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::InitThinkStates
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
for (size_t i = 0; i < NUM_THINKSTATES; i++)
|
|
|
|
{
|
|
|
|
m_ThinkMap[i] = THINK_VOID;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < NUM_THINKLEVELS; i++)
|
|
|
|
{
|
|
|
|
m_Think[i] = THINK_VOID;
|
|
|
|
m_ThinkStates[i] = THINKSTATE_VOID;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ThinkMap[THINKSTATE_VOID] = THINK_VOID;
|
|
|
|
m_ThinkMap[THINKSTATE_IDLE] = THINK_IDLE;
|
|
|
|
m_ThinkMap[THINKSTATE_PAIN] = THINK_PAIN;
|
|
|
|
m_ThinkMap[THINKSTATE_KILLED] = THINK_KILLED;
|
|
|
|
m_ThinkMap[THINKSTATE_ATTACK] = THINK_TURRET;
|
|
|
|
m_ThinkMap[THINKSTATE_CURIOUS] = THINK_CURIOUS;
|
|
|
|
m_ThinkMap[THINKSTATE_DISGUISE] = THINK_DISGUISE_SALUTE;
|
|
|
|
m_ThinkMap[THINKSTATE_GRENADE] = THINK_GRENADE;
|
|
|
|
m_ThinkMap[THINKSTATE_NOCLIP] = THINK_NOCLIP;
|
|
|
|
|
|
|
|
m_ThinkLevel = THINKLEVEL_NORMAL;
|
|
|
|
m_ThinkState = THINKSTATE_VOID;
|
|
|
|
m_bDirtyThinkState = false;
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DefaultRestart
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Default restart of current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DefaultRestart
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
EndState( m_ThinkLevel );
|
|
|
|
BeginState();
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::SuspendState
|
2019-06-30 02:42:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Suspend current think state.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::SuspendState
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ];
|
|
|
|
|
|
|
|
if( func->SuspendState )
|
|
|
|
( this->*func->SuspendState )( );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ResumeState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Resume current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ResumeState
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ];
|
|
|
|
|
|
|
|
if( func->ResumeState )
|
|
|
|
( this->*func->ResumeState )( );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::BeginState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Begin current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::BeginState
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Think[ m_ThinkLevel ] = m_ThinkMap[ m_ThinkState ];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ];
|
|
|
|
|
|
|
|
if( func->BeginState )
|
|
|
|
( this->*func->BeginState )();
|
|
|
|
|
|
|
|
m_Think[ m_ThinkLevel ] = m_ThinkMap[ m_ThinkState ];
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EndState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
End current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EndState
|
|
|
|
(
|
|
|
|
int level
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ level ] ];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Think[ level ] = THINK_VOID;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( func->EndState )
|
|
|
|
( this->*func->EndState )();
|
|
|
|
|
|
|
|
if( m_pAnimThread )
|
|
|
|
m_pAnimThread->AbortRegistration( STRING_EMPTY, this );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::RestartState
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Restart current think state.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::RestartState
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[ m_Think[ m_ThinkLevel ] ];
|
|
|
|
|
|
|
|
if( func->RestartState)
|
|
|
|
( this->*func->RestartState)();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::UpdateEnableEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Enable/disable enemy based on desired value.
|
|
|
|
Can be changed from script.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::UpdateEnableEnemy
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_bEnableEnemy != m_bDesiredEnableEnemy)
|
|
|
|
{
|
|
|
|
m_bEnableEnemy = m_bDesiredEnableEnemy;
|
|
|
|
if (m_bDesiredEnableEnemy)
|
|
|
|
{
|
|
|
|
SetLeashHome(origin);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_ThinkStates[THINKLEVEL_NORMAL] <= THINKSTATE_DISGUISE)
|
|
|
|
{
|
|
|
|
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
|
|
|
}
|
|
|
|
SetEnemy(NULL, false);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ThinkStateTransitions
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Transition think state and level.
|
|
|
|
Called when thinkstate/level are change.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ThinkStateTransitions
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int newThinkLevel;
|
|
|
|
int newThinkState;
|
|
|
|
|
|
|
|
//GlobalFuncs_t *func;// = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
|
|
|
//loop on all think levels.
|
|
|
|
for (newThinkLevel = NUM_THINKLEVELS -1; newThinkLevel >= 0 ; newThinkLevel--)
|
|
|
|
{
|
|
|
|
newThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
//a new think level is found if it's think state is not THINKSTATE_VOID
|
|
|
|
if (newThinkState != THINKSTATE_VOID)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ThinkMap[newThinkState] == m_Think[m_ThinkLevel])
|
|
|
|
{
|
|
|
|
if (newThinkLevel != m_ThinkLevel || m_ThinkState != newThinkState)
|
|
|
|
{
|
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = (eThinkState)newThinkState;
|
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[newThinkState];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RestartState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (newThinkLevel > THINKLEVEL_NORMAL)
|
|
|
|
{
|
|
|
|
for (int i = 0 ; i < newThinkLevel; i++)
|
|
|
|
{
|
|
|
|
if (m_ThinkStates[i] == THINKSTATE_VOID)
|
|
|
|
EndState(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newThinkLevel > m_ThinkLevel)
|
|
|
|
{
|
|
|
|
SuspendState();
|
|
|
|
|
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EndState(m_ThinkLevel);
|
|
|
|
|
|
|
|
if (newThinkLevel == m_ThinkLevel)
|
|
|
|
{
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
|
|
|
|
|
|
|
|
if (m_Think[newThinkLevel] != m_ThinkMap[m_ThinkState])
|
|
|
|
{
|
|
|
|
EndState(newThinkLevel);
|
|
|
|
|
|
|
|
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ResumeState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::FixAIParameters
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Fix path related parameters.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FixAIParameters
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: needs revision(silly mistakes)
|
|
|
|
|
|
|
|
float distmin, distmin2, distmax;
|
|
|
|
if (m_pTetherEnt)
|
|
|
|
{
|
|
|
|
float leash = 64;
|
|
|
|
if ( m_pTetherEnt->IsSubclassOfEntity() )
|
|
|
|
{
|
|
|
|
leash = m_pTetherEnt->angles.y - m_pTetherEnt->origin.y + m_pTetherEnt->angles.z + m_pTetherEnt->origin.z;
|
|
|
|
}
|
|
|
|
if ( leash <= m_fLeash)
|
|
|
|
{
|
|
|
|
distmin = m_fLeash;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing leash from %g to %g.\n"
|
|
|
|
"^~^~^ Leash must be larger than the size of the entity to which an AI is tethered.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
m_fLeash,
|
|
|
|
leash);
|
|
|
|
m_fLeash = leash;
|
|
|
|
distmin = leash;
|
|
|
|
m_fLeashSquared = Square(leash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
distmin = m_fLeash;
|
|
|
|
}
|
|
|
|
if (m_fMinDistance <= distmin)
|
|
|
|
{
|
|
|
|
distmax = m_fMinDistance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to match leash.\n"
|
|
|
|
"^~^~^ Leash must be greater than mindist, or the AI will want to both run away and stay put.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
m_fMinDistance,
|
|
|
|
distmin);
|
|
|
|
m_fMinDistance = distmin;
|
|
|
|
distmax = distmin;
|
|
|
|
m_fMinDistanceSquared = distmin * distmin;
|
|
|
|
}
|
|
|
|
distmax += 128;
|
|
|
|
if (distmax - 1 > m_fMaxDistance)
|
|
|
|
{
|
|
|
|
Com_Printf("^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing maxdist from %g to %g to exceed mindist.\n"
|
|
|
|
"^~^~^ Maxdist should be %i greater than mindist, or the AI will want to both run away and charge, or just do oscillatory behavior.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
m_fMaxDistance,
|
|
|
|
distmax,
|
|
|
|
128);
|
|
|
|
|
|
|
|
m_fMaxDistance = distmax;
|
|
|
|
m_fMaxDistanceSquared = distmax * distmax;
|
|
|
|
}
|
|
|
|
if (world->farplane_distance > 0)
|
|
|
|
{
|
|
|
|
//FIXME: macro and floats
|
|
|
|
if (m_fMaxDistance > world->farplane_distance * 0.828 +1)
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing maxdist from %g to %g to be %g%% of farplane.\n"
|
|
|
|
"^~^~^ Maxdist should be this distance within fog, or AI will be able to see and attack through fog.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
m_fMaxDistance,
|
|
|
|
world->farplane_distance * 0.828,
|
|
|
|
2.0);
|
|
|
|
distmin2 = m_fMinDistance;
|
|
|
|
m_fMaxDistance = world->farplane_distance * 0.828;
|
|
|
|
m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance;
|
|
|
|
if (distmin2 + 128.0 - 1.0 > m_fMaxDistance)
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to be less than maxdist "
|
|
|
|
"after fog adjustment.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
distmin2,
|
|
|
|
m_fMaxDistance <= 128 ? 0 : m_fMaxDistance - 128);
|
|
|
|
m_fMinDistance = m_fMaxDistance - 128.0;
|
|
|
|
if (m_fMaxDistance - 128.0 < 0)
|
|
|
|
{
|
|
|
|
m_fMinDistance = 0.0;
|
|
|
|
}
|
|
|
|
m_fMinDistanceSquared = Square(m_fMinDistance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::AttackEntryAnimation
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor stands/draws his weapon.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::AttackEntryAnimation
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (level.inttime >= level.m_iAttackEntryAnimTime + 3000)
|
|
|
|
{
|
|
|
|
float distSq = (m_Enemy->origin - origin).lengthXYSquared();
|
|
|
|
|
|
|
|
if (m_bNoSurprise || distSq >= Square(256))
|
|
|
|
{
|
|
|
|
if (distSq > Square(1024) && !(rand() & 3))
|
|
|
|
{
|
|
|
|
if (m_pNextSquadMate != this)
|
|
|
|
{
|
|
|
|
for (auto pSquadMate = m_pNextSquadMate; ; pSquadMate = pSquadMate->m_pNextSquadMate)
|
|
|
|
{
|
|
|
|
if (Square(m_fInterval) * Square(2) > (pSquadMate->origin - origin).lengthSquared())
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pSquadMate == this)
|
|
|
|
{
|
|
|
|
if (m_bNewEnemy)
|
|
|
|
Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false);
|
|
|
|
|
|
|
|
m_bNoSurprise = true;
|
|
|
|
m_bNewEnemy = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = m_Enemy->origin.x - origin.x;
|
|
|
|
vDelta[1] = m_Enemy->origin.y - origin.y;
|
|
|
|
if (vDelta[0] != 0 || vDelta[1] != 0)
|
|
|
|
{
|
|
|
|
SetDesiredYawDir(vDelta);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredLookDir(m_Enemy->origin - origin);
|
|
|
|
|
|
|
|
m_csNextAnimString = STRING_ANIM_STANDIDENTIFY_SCR;
|
|
|
|
|
|
|
|
m_bNextForceStart = true;
|
|
|
|
m_bNoSurprise = true;
|
|
|
|
m_bNewEnemy = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
if ( rand() > distSq * 0.0026041667) //rand() / 0x17F
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
StartAnimation(1, STRING_ANIM_STANDSHOCK_SCR);
|
|
|
|
m_bNoSurprise = true;
|
|
|
|
m_bNewEnemy = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
if (m_bNewEnemy)
|
|
|
|
Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false);
|
|
|
|
|
|
|
|
m_bNoSurprise = true;
|
|
|
|
m_bNewEnemy = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CheckForThinkStateTransition
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Check for all thinkstates transitions.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::CheckForThinkStateTransition
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL))
|
|
|
|
{
|
|
|
|
if (!m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!CheckForTransition(THINKSTATE_ATTACK, THINKLEVEL_NORMAL))
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!CheckForTransition(THINKSTATE_DISGUISE, THINKLEVEL_NORMAL))
|
|
|
|
{
|
|
|
|
|
|
|
|
if (CheckForTransition(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL))
|
|
|
|
{
|
|
|
|
m_pszDebugState = "from_sight";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CheckForTransition
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Check for thinkstate transition.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CheckForTransition
|
|
|
|
(
|
|
|
|
eThinkState state,
|
|
|
|
eThinkLevel level
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_ThinkStates[ level ] != state )
|
|
|
|
{
|
|
|
|
func = &GlobalFuncs[ m_ThinkMap[ state ] ];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( func->PassesTransitionConditions && ( this->*( func->PassesTransitionConditions ) )() )
|
|
|
|
{
|
|
|
|
SetThinkState( state, THINKLEVEL_NORMAL);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::PassesTransitionConditions_Grenade
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Should actor transition think state to grenade ?
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::PassesTransitionConditions_Grenade
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if( !m_bLockThinkState && m_bEnableEnemy && m_pGrenade )
|
|
|
|
{
|
|
|
|
return m_fGrenadeAwareness >= random();
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PassesTransitionConditions_Attack
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Should actor transition think state to attack ?
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Attack
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateEnemy(0);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_bLockThinkState )
|
|
|
|
return false;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_Enemy && !( m_Enemy->flags & FL_NOTARGET ) )
|
|
|
|
{
|
|
|
|
if(EnemyIsDisguised())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_PotentialEnemies.GetCurrentVisibility() > 0.999f )
|
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::PassesTransitionConditions_Disguise
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Should actor transition think state to disguise ?
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::PassesTransitionConditions_Disguise
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if( m_bLockThinkState )
|
|
|
|
return false;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_iNextDisguiseTime > level.inttime )
|
|
|
|
return false;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iNextDisguiseTime = level.inttime + 200;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateEnemy(200);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( !m_Enemy )
|
|
|
|
return false;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if(EnemyIsDisguised())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if( m_PotentialEnemies.GetCurrentVisibility() > 0.999f )
|
|
|
|
{
|
|
|
|
if( fabs( m_Enemy->origin[ 2 ] - origin[ 2 ] ) <= 48.0f )
|
|
|
|
{
|
|
|
|
vec2_t delta;
|
|
|
|
float fHorzDistanceSquared;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorSub2D(m_Enemy->origin, origin, delta);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fHorzDistanceSquared = VectorLength2DSquared(delta);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if(fHorzDistanceSquared > Square(32) && fHorzDistanceSquared < m_fMaxDisguiseDistSquared)
|
|
|
|
{
|
|
|
|
Player *player = ( Player * )G_GetEntity( 0 );
|
|
|
|
Vector pos = EyePosition();
|
|
|
|
|
|
|
|
return G_SightTrace(
|
|
|
|
pos,
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
player->centroid,
|
|
|
|
this,
|
|
|
|
player,
|
|
|
|
MASK_TRANSITION,
|
|
|
|
qfalse,
|
|
|
|
"Actor::PassesTransitionConditions_Disguise" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PassesTransitionConditions_Curious
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Should actor transition think state to curious ?
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Curious
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateEnemy(200);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( m_bLockThinkState )
|
|
|
|
return false;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( !m_Enemy && m_iCuriousTime )
|
|
|
|
{
|
|
|
|
SetCuriousAnimHint(6);
|
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if(m_Enemy && !EnemyIsDisguised() && m_PotentialEnemies.GetCurrentVisibility() <= 0.999f )
|
|
|
|
{
|
|
|
|
//THINKSTATE_CURIOUS
|
|
|
|
SetCuriousAnimHint(6);
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PassesTransitionConditions_Idle
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Should actor transition think state to idle ?
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Idle
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
glbs.Printf("PassesTransitionConditions_Idle\n");
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateEnemy(500);
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_bLockThinkState)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!m_Enemy && !m_iCuriousTime)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetRunAnim
|
|
|
|
(
|
|
|
|
Event* ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddConstString(GetRunAnim());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetWalkAnim
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(GetWalkAnim());
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PathDistanceAlongVector
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns projected distance from vDir along path.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
float Actor::PathDistanceAlongVector
|
|
|
|
(
|
|
|
|
vec3_t vDir
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vDelta = m_Path.CurrentDelta();
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return DotProduct2D( vDelta, vDir );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::FaceEnemyOrMotion
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FaceEnemyOrMotion
|
|
|
|
(
|
|
|
|
int iTimeIntoMove
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vDelta = origin - m_vLastEnemyPos;
|
|
|
|
vDelta.z = 0;
|
|
|
|
if (iTimeIntoMove > 999)
|
|
|
|
{
|
|
|
|
if (m_Path.CurrentNodeIndex() != m_sCurrentPathNodeIndex)
|
|
|
|
{
|
|
|
|
float fDist = PathDistanceAlongVector(vDelta);
|
|
|
|
m_bFaceEnemy = fDist <= 0 || vDelta.lengthXYSquared() * Square(64) >= Square(fDist);
|
|
|
|
|
|
|
|
m_sCurrentPathNodeIndex = m_Path.CurrentNodeIndex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bFaceEnemy = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_bFaceEnemy && (vDelta.x >= 15.0 || vDelta.x <= -15.0 || vDelta.y >= 15.0 || vDelta.y <= -15.0))
|
|
|
|
{
|
|
|
|
vDelta.x = -vDelta.x;
|
|
|
|
vDelta.y = -vDelta.y;
|
|
|
|
FaceDirectionDuringMotion(vDelta);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FaceMotion();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::FaceDirectionDuringMotion
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Face direction during motion.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FaceDirectionDuringMotion
|
|
|
|
(
|
|
|
|
vec3_t vLook
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float yaw;
|
|
|
|
|
|
|
|
SetDesiredLookDir(vLook);
|
|
|
|
|
|
|
|
|
|
|
|
if (velocity[0] != 0 || velocity[1] != 0)
|
|
|
|
{
|
|
|
|
float fMagsSquared = VectorLength2DSquared(vLook) * VectorLength2DSquared(velocity);
|
|
|
|
float fDot = DotProduct2D(velocity, vLook);
|
|
|
|
float fDotSquared = Square(fDot);
|
|
|
|
|
|
|
|
yaw = velocity.toYaw();
|
|
|
|
|
|
|
|
float fYaw2;
|
|
|
|
if (fMagsSquared * 0.5 < fDotSquared)
|
|
|
|
{
|
|
|
|
if (fDot >= 0)
|
|
|
|
{
|
|
|
|
fYaw2 = yaw;
|
|
|
|
}
|
|
|
|
else if (yaw - 180 >= 0)
|
|
|
|
{
|
|
|
|
fYaw2 = yaw - 180;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fYaw2 = yaw - 180 + 360;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (vLook[0] * velocity[1] <= vLook[1] * velocity[0])
|
|
|
|
{
|
|
|
|
fYaw2 = yaw - 270;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fYaw2 = yaw - 90;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fYaw2 < 0)
|
|
|
|
{
|
|
|
|
fYaw2 += 360;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYaw(fYaw2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetDesiredYawDir(vLook);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetAnimName
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddConstString(m_csAnimName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetAnimName
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_csAnimName = ev->GetConstString(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetDisguiseRange
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float range = ev->GetFloat(1);
|
|
|
|
m_fMaxDisguiseDistSquared = Square(range);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetDisguiseRange
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(sqrt(m_fMaxDisguiseDistSquared));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetDisguisePeriod
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_iDisguisePeriod = ev->GetFloat(1) * 1000 + 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetDisguisePeriod
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_iDisguisePeriod / 1000.0);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::FaceMotion
|
2018-09-17 23:50:38 +02:00
|
|
|
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FaceMotion
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector delta;
|
|
|
|
|
|
|
|
if (VectorLength2DSquared(velocity) > 1)
|
|
|
|
{
|
|
|
|
vec3_t dir;
|
|
|
|
velocity.copyTo(dir);
|
|
|
|
delta = origin - m_vOriginHistory[m_iCurrentHistory];
|
|
|
|
|
|
|
|
if (delta.lengthXYSquared() >= 1)
|
|
|
|
{
|
|
|
|
if (DotProduct2D(velocity, delta) > 0)
|
|
|
|
{
|
|
|
|
delta.copyTo(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsIdleState(m_ThinkState))
|
|
|
|
{
|
|
|
|
IdleLook(dir);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetDesiredLookDir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYawDir(dir);
|
|
|
|
}
|
|
|
|
else if (IsIdleState(m_ThinkState) && m_pLookEntity)
|
|
|
|
{
|
|
|
|
LookAtLookEntity();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::ForceAttackPlayer
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, (Sentient *)G_GetEntity(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventAttackPlayer
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Player *pPlayer = (Player *)G_GetEntity(0);
|
|
|
|
if (!pPlayer)
|
|
|
|
{
|
|
|
|
ScriptError("player doesn't exist");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, pPlayer);
|
|
|
|
m_bForceAttackPlayer = true;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventShareEnemy
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Share enemy with squad mates.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventShareEnemy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
if (!EnemyIsDisguised())
|
|
|
|
{
|
|
|
|
for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer())
|
|
|
|
{
|
|
|
|
if (pSquadMate->IsSubclassOfActor())
|
|
|
|
{
|
|
|
|
Vector dist = pSquadMate->origin - origin;
|
|
|
|
float distSq = dist * dist;
|
|
|
|
if (pSquadMate->m_fMaxShareDistSquared == 0.0 || distSq <= pSquadMate->m_fMaxShareDistSquared)
|
|
|
|
{
|
|
|
|
pSquadMate->m_PotentialEnemies.ConfirmEnemyIfCanSeeSharerOrEnemy(pSquadMate, this, m_Enemy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::EventShareGrenade
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Share grenade with squad mates.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventShareGrenade
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (m_pGrenade)
|
|
|
|
{
|
|
|
|
for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer())
|
|
|
|
{
|
|
|
|
if (pSquadMate->IsSubclassOfActor())
|
|
|
|
{
|
|
|
|
if (!pSquadMate->m_pGrenade)
|
|
|
|
{
|
|
|
|
Vector dist = pSquadMate->origin - origin;
|
|
|
|
float distSq = Square(dist);
|
|
|
|
|
|
|
|
if (distSq < Square(768))
|
|
|
|
{
|
|
|
|
|
|
|
|
if (DoesTheoreticPathExist(pSquadMate->origin, 1536))
|
|
|
|
{
|
|
|
|
pSquadMate->SetGrenade(m_pGrenade);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ReceiveAIEvent
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Calls proper RecieveAIEvent for current ThinkState.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::ReceiveAIEvent
|
|
|
|
(
|
|
|
|
vec3_t event_origin,
|
|
|
|
int iType,
|
|
|
|
Entity *originator,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (originator != this && originator != GetActiveWeapon(WEAPON_MAIN))
|
|
|
|
{
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2019-06-29 23:43:30 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (func->ReceiveAIEvent)
|
|
|
|
(this->*func->ReceiveAIEvent)(event_origin, iType, originator, fDistSquared, fMaxDistSquared);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DefaultReceiveAIEvent
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Default AI event handler.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DefaultReceiveAIEvent
|
|
|
|
(
|
|
|
|
vec3_t event_origin,
|
|
|
|
int iType,
|
|
|
|
Entity *originator,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (!IsDead())
|
|
|
|
{
|
|
|
|
if (!originator->IsDead() && originator->IsSubclassOfSentient() && ((Sentient *)originator)->m_Team == m_Team && !IsSquadMate((Sentient *)originator))
|
|
|
|
{
|
|
|
|
MergeWithSquad((Sentient *)originator);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (iType)
|
|
|
|
{
|
|
|
|
case AI_EVENT_WEAPON_FIRE:
|
|
|
|
case AI_EVENT_WEAPON_IMPACT:
|
|
|
|
if ( Square(m_fHearing) > fDistSquared)
|
|
|
|
WeaponSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator);
|
|
|
|
break;
|
|
|
|
case AI_EVENT_EXPLOSION:
|
|
|
|
case AI_EVENT_MISC:
|
|
|
|
case AI_EVENT_MISC_LOUD:
|
|
|
|
if ( Square(m_fHearing) > fDistSquared)
|
|
|
|
CuriousSound(iType, event_origin, fDistSquared, fMaxDistSquared);
|
|
|
|
break;
|
|
|
|
case AI_EVENT_AMERICAN_VOICE:
|
|
|
|
case AI_EVENT_GERMAN_VOICE:
|
|
|
|
case AI_EVENT_AMERICAN_URGENT:
|
|
|
|
case AI_EVENT_GERMAN_URGENT:
|
|
|
|
if ( Square(m_fHearing) > fDistSquared)
|
|
|
|
VoiceSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator);
|
|
|
|
break;
|
|
|
|
case AI_EVENT_FOOTSTEP:
|
|
|
|
if ( Square(m_fHearing) > fDistSquared)
|
|
|
|
FootstepSound(event_origin, fDistSquared, fMaxDistSquared, originator);
|
|
|
|
break;
|
|
|
|
case AI_EVENT_GRENADE:
|
|
|
|
GrenadeNotification(originator);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"unknown ai_event type\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("iType = %i", iType));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::PriorityForEventType
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns priority for event type.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
int Actor::PriorityForEventType
|
|
|
|
(
|
|
|
|
int iType
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch( iType )
|
|
|
|
{
|
|
|
|
|
|
|
|
//FIXME: return macros
|
|
|
|
case AI_EVENT_WEAPON_FIRE:
|
|
|
|
return 7;
|
|
|
|
case AI_EVENT_WEAPON_IMPACT:
|
|
|
|
return 5;
|
|
|
|
case AI_EVENT_EXPLOSION:
|
|
|
|
return 6;
|
|
|
|
case AI_EVENT_AMERICAN_VOICE:
|
|
|
|
case AI_EVENT_GERMAN_VOICE:
|
|
|
|
return 3;
|
|
|
|
case AI_EVENT_AMERICAN_URGENT:
|
|
|
|
case AI_EVENT_GERMAN_URGENT:
|
|
|
|
return 4;
|
|
|
|
case AI_EVENT_MISC:
|
|
|
|
return 1;
|
|
|
|
case AI_EVENT_MISC_LOUD:
|
|
|
|
case AI_EVENT_FOOTSTEP:
|
|
|
|
return 2;
|
|
|
|
case AI_EVENT_GRENADE:
|
|
|
|
return 8;
|
|
|
|
default:
|
|
|
|
assert( !"PriorityForEventType: unknown ai_event type" );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *DebugStringForEvent(int iType)
|
|
|
|
{
|
|
|
|
switch (iType) {
|
|
|
|
case AI_EVENT_WEAPON_FIRE:
|
|
|
|
return "weapon_fire";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_WEAPON_IMPACT:
|
|
|
|
return "weapon_impact";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_EXPLOSION:
|
|
|
|
return "explosion";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_AMERICAN_VOICE:
|
|
|
|
return "american_voice";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_GERMAN_VOICE:
|
|
|
|
return "german_voice";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_AMERICAN_URGENT:
|
|
|
|
return "american_urgent";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_GERMAN_URGENT:
|
|
|
|
return "german_urgent";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_MISC:
|
|
|
|
return "misc";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_MISC_LOUD:
|
|
|
|
return "misc_loud";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_FOOTSTEP:
|
|
|
|
return "footstep";
|
|
|
|
break;
|
|
|
|
case AI_EVENT_GRENADE:
|
|
|
|
return "grenade";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return "????";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CuriousSound
|
|
|
|
|
|
|
|
Handles curious sound.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::CuriousSound
|
|
|
|
(
|
|
|
|
int iType,
|
|
|
|
vec3_t sound_origin,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float v7, v8, fRangeFactor = 1.0;
|
|
|
|
int iPriority;
|
|
|
|
if (m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
if (m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE || m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS)
|
|
|
|
{
|
|
|
|
//FIXME: name variables.
|
|
|
|
if (fMaxDistSquared != 0.0)
|
|
|
|
{
|
|
|
|
v7 = 1*(1.0/3) - fDistSquared * (1*(1.0 / 3)) / fMaxDistSquared;
|
|
|
|
if (v7 <= 1.0)
|
|
|
|
fRangeFactor = v7;
|
|
|
|
}
|
|
|
|
v8 = fRangeFactor * m_fSoundAwareness;
|
|
|
|
//FIXME: macro
|
|
|
|
if (v8 >= rand() * 0.000000046566129)
|
|
|
|
{
|
|
|
|
RaiseAlertnessForEventType(iType);
|
|
|
|
iPriority = PriorityForEventType(iType);
|
|
|
|
if (iPriority >= m_iCuriousLevel)
|
|
|
|
{
|
|
|
|
m_iCuriousLevel = iPriority;
|
|
|
|
if (iType == AI_EVENT_WEAPON_IMPACT)
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
if (fDistSquared <= Square(192))
|
|
|
|
SetCuriousAnimHint(1);
|
|
|
|
}
|
|
|
|
else if (iType > AI_EVENT_WEAPON_IMPACT)
|
|
|
|
{
|
|
|
|
if (iType == AI_EVENT_EXPLOSION)
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
if (fDistSquared <= Square(768))
|
|
|
|
SetCuriousAnimHint(3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetCuriousAnimHint(5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (iType == AI_EVENT_WEAPON_FIRE)
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
if (fDistSquared <= Square(512))
|
|
|
|
SetCuriousAnimHint(2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetCuriousAnimHint(5);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnemyPos(sound_origin);
|
|
|
|
|
|
|
|
EndCurrentThinkState();
|
|
|
|
SetThinkState(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL);
|
|
|
|
|
|
|
|
m_pszDebugState = G_AIEventStringFromType(iType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::WeaponSound
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Handles weapon sound.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::WeaponSound
|
|
|
|
(
|
|
|
|
int iType,
|
|
|
|
vec3_t sound_origin,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared,
|
|
|
|
Entity *originator
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Sentient *pOwner;
|
|
|
|
gi.Printf("Actor::WeaponSound");
|
|
|
|
if (originator->IsSubclassOfWeapon())
|
|
|
|
{
|
|
|
|
pOwner = ((Weapon *)originator)->GetOwner();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!originator->IsSubclassOfProjectile())
|
|
|
|
{
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"Actor::WeaponSound: non-weapon made a weapon sound.\\n\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("class = %s", originator->getClassname()));
|
|
|
|
assert(false && assertStr);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pOwner = ((Projectile *)originator)->GetOwner();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pOwner)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Sentient *pEnemy;
|
|
|
|
|
|
|
|
pEnemy = pOwner->m_Enemy;
|
|
|
|
if (pOwner->m_Team == m_Team)
|
|
|
|
{
|
|
|
|
if (!pEnemy)
|
|
|
|
{
|
|
|
|
if (pOwner->IsSubclassOfActor())
|
|
|
|
{
|
|
|
|
Actor *pAOwner = (Actor *)pOwner;
|
|
|
|
//FIXME: macro
|
|
|
|
if (originator->IsSubclassOfWeapon() && pAOwner->m_Think[0] == THINK_MACHINEGUNNER)
|
|
|
|
{
|
|
|
|
Weapon *pWOriginator = (Weapon *)originator;
|
|
|
|
if (pWOriginator->aim_target)
|
|
|
|
{
|
|
|
|
if (pWOriginator->aim_target->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
if (((Sentient *)(pWOriginator->aim_target.Pointer()))->m_Team != pAOwner->m_Team)
|
|
|
|
pEnemy = (Sentient *)(pWOriginator->aim_target.Pointer());
|
|
|
|
}
|
|
|
|
else if (pAOwner->m_Team == TEAM_GERMAN)
|
|
|
|
{
|
|
|
|
for (pEnemy = level.m_HeadSentient[1]; ; pEnemy = pEnemy->m_NextSentient)
|
|
|
|
{
|
|
|
|
if (!pEnemy)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Vector vDist = pEnemy->centroid - pWOriginator->aim_target->origin;
|
|
|
|
if (vDist.lengthSquared() <= 2304 || vDist.lengthSquared() != 2304)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!pEnemy)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!pEnemy)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//v14 = &this->m_PotentialEnemies;
|
|
|
|
if (m_PotentialEnemies.CaresAboutPerfectInfo(pEnemy))
|
|
|
|
{
|
|
|
|
float fDist = sqrt(fDistSquared);
|
|
|
|
if (NoticeShot(pOwner, pEnemy, fDist))
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, pOwner);
|
|
|
|
CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::FootstepSound
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Handles footstep sound.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::FootstepSound
|
|
|
|
(
|
|
|
|
vec3_t sound_origin,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared,
|
|
|
|
Entity *originator
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (originator->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
if ( (m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE || m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS ) && m_bEnableEnemy)
|
|
|
|
{
|
|
|
|
if (NoticeFootstep((Sentient *)originator))
|
|
|
|
{
|
|
|
|
CuriousSound(AI_EVENT_FOOTSTEP, sound_origin, fDistSquared, fMaxDistSquared);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"'ai_event footstep' in a tiki used by something besides AI or player.\\n\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::VoiceSound
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Handles voice sound.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::VoiceSound
|
|
|
|
(
|
|
|
|
int iType,
|
|
|
|
vec3_t sound_origin,
|
|
|
|
float fDistSquared,
|
|
|
|
float fMaxDistSquared,
|
|
|
|
Entity *originator
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bool bFriendly;
|
|
|
|
//FIXME: macros
|
|
|
|
if ((m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_CURIOUS) || !m_bEnableEnemy)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bFriendly = m_Team == TEAM_GERMAN;
|
|
|
|
|
|
|
|
if (iType <= AI_EVENT_GERMAN_VOICE)
|
|
|
|
{
|
|
|
|
assert(iType == AI_EVENT_AMERICAN_VOICE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(iType <= AI_EVENT_GERMAN_URGENT);
|
|
|
|
|
|
|
|
if (iType == AI_EVENT_AMERICAN_URGENT)
|
|
|
|
{
|
|
|
|
bFriendly = m_Team == TEAM_AMERICAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bFriendly)
|
|
|
|
{
|
|
|
|
if (NoticeVoice((Sentient *)originator))
|
|
|
|
{
|
|
|
|
CuriousSound(iType, sound_origin, fDistSquared, fMaxDistSquared);
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GrenadeNotification
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Handles grenade notification.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::GrenadeNotification
|
|
|
|
(
|
|
|
|
Entity *originator
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!m_pGrenade)
|
|
|
|
{
|
|
|
|
if (CanSeeFOV(originator))
|
|
|
|
{
|
|
|
|
assert(originator->IsSubclassOfProjectile());
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetGrenade(originator);
|
|
|
|
Event e1(EV_Actor_ShareGrenade);
|
|
|
|
PostEvent(e1, 0.5);
|
|
|
|
|
|
|
|
Anim_Say(STRING_ANIM_SAY_GRENADE_SIGHTED_SCR, 0, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_pGrenade == originator)
|
|
|
|
{
|
|
|
|
|
|
|
|
float fGrav, fDeltaZ, fVelDivGrav, fTimeLand;
|
|
|
|
vec2_t vLand;
|
|
|
|
vec2_t vMove;
|
|
|
|
|
|
|
|
fGrav = sv_gravity->value * m_pGrenade->gravity;
|
|
|
|
|
|
|
|
fDeltaZ = originator->origin[2] - origin[2];
|
|
|
|
|
|
|
|
fVelDivGrav = originator->velocity[2] / fGrav;
|
|
|
|
|
|
|
|
//from s=v*t + 0.5*a*t^2, apply for z velocity, solve.
|
|
|
|
fTimeLand = fVelDivGrav + sqrt((fDeltaZ + fDeltaZ) / fGrav + Square(fVelDivGrav));
|
|
|
|
|
|
|
|
|
|
|
|
VectorMA2D(originator->origin, fTimeLand, originator->velocity, vLand);
|
|
|
|
|
|
|
|
VectorSub2D(m_vGrenadePos, vLand, vMove);
|
|
|
|
|
|
|
|
if (VectorLength2D(vMove) > 16)
|
|
|
|
{
|
|
|
|
m_vGrenadePos = Vector(vLand[0], vLand[1], origin[2]);
|
|
|
|
m_bGrenadeBounced = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::SetGrenade
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Set current grenade.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetGrenade
|
|
|
|
(
|
|
|
|
Entity *pGrenade
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pGrenade = pGrenade;
|
|
|
|
|
|
|
|
m_bGrenadeBounced = true;
|
|
|
|
|
|
|
|
m_iFirstGrenadeTime = level.inttime;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vGrenadePos = pGrenade->origin;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::NotifySquadmateKilled
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Handle squadmate killed notification.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::NotifySquadmateKilled
|
|
|
|
(
|
|
|
|
Sentient *pSquadMate,
|
|
|
|
Sentient *pAttacker
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_PotentialEnemies.CaresAboutPerfectInfo(pAttacker))
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector dist = pSquadMate->origin - origin;
|
|
|
|
float distSq = dist * dist;
|
|
|
|
if (distSq < m_fSight*m_fSight)
|
|
|
|
{
|
|
|
|
bool shouldConfirm = false;
|
|
|
|
if (gi.AreasConnected(edict->r.areanum,pSquadMate->edict->r.areanum))
|
|
|
|
{
|
|
|
|
shouldConfirm = G_SightTrace(
|
|
|
|
EyePosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
pSquadMate->EyePosition(),
|
|
|
|
this,
|
|
|
|
pSquadMate,
|
|
|
|
MASK_TRANSITION,
|
|
|
|
qfalse,
|
|
|
|
"Actor::NotifySquadmateKilled");
|
|
|
|
}
|
|
|
|
//FIXME: macro for that constant
|
|
|
|
if (!shouldConfirm)
|
|
|
|
{
|
|
|
|
if (distSq <= Square(768))
|
|
|
|
{
|
|
|
|
Vector start, end;
|
|
|
|
if (origin.z <= pSquadMate->origin.z)
|
|
|
|
{
|
|
|
|
start = origin;
|
|
|
|
end = pSquadMate->origin;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start = pSquadMate->origin;
|
|
|
|
end = origin;
|
|
|
|
}
|
|
|
|
shouldConfirm = m_Path.DoesTheoreticPathExist(start, end, this, 1536, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (shouldConfirm)
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, pAttacker);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::RaiseAlertnessForEventType
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Raise alertness(enemy notice) for specifc event.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::RaiseAlertnessForEventType
|
|
|
|
(
|
|
|
|
int iType
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fAmount;
|
|
|
|
|
|
|
|
switch (iType)
|
|
|
|
{
|
|
|
|
case AI_EVENT_WEAPON_FIRE:
|
|
|
|
fAmount = 0.2f;
|
|
|
|
case AI_EVENT_WEAPON_IMPACT:
|
|
|
|
fAmount = 0.1f;
|
|
|
|
case AI_EVENT_EXPLOSION:
|
|
|
|
fAmount = 0.4f;
|
|
|
|
case AI_EVENT_AMERICAN_VOICE:
|
|
|
|
case AI_EVENT_AMERICAN_URGENT:
|
|
|
|
if (m_Team == TEAM_AMERICAN)
|
|
|
|
return;
|
|
|
|
fAmount = 0.25f;
|
|
|
|
case AI_EVENT_MISC:
|
|
|
|
fAmount = 0.02f;
|
|
|
|
case AI_EVENT_MISC_LOUD:
|
|
|
|
case AI_EVENT_FOOTSTEP:
|
|
|
|
fAmount = 0.05f;
|
|
|
|
case AI_EVENT_GRENADE:
|
|
|
|
fAmount = 0.04f;
|
|
|
|
break;
|
|
|
|
case AI_EVENT_GERMAN_VOICE:
|
|
|
|
case AI_EVENT_GERMAN_URGENT:
|
|
|
|
if (m_Team == TEAM_AMERICAN)
|
|
|
|
{
|
|
|
|
RaiseAlertness(0.25);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"Actor::RaiseAlertnessForEventType: unknown event type\\n\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RaiseAlertness(fAmount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::RaiseAlertness
|
|
|
|
|
|
|
|
Lower enemy notice time by fAmount.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::RaiseAlertness
|
|
|
|
(
|
|
|
|
float fAmount
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float fMaxAmount;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fMaxAmount = m_fNoticeTimeScale * 2/3;
|
|
|
|
|
|
|
|
m_fNoticeTimeScale -= fAmount <= fMaxAmount ? fAmount : fMaxAmount;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::NoticeShot
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if shooter is an enemy.
|
|
|
|
Otherwise the shooter is a team mate and target is registered an enemy if he's visible/reachable.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::NoticeShot
|
|
|
|
(
|
|
|
|
Sentient *pShooter,
|
|
|
|
Sentient *pTarget,
|
|
|
|
float fDist
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.Printf("Notice shot");
|
|
|
|
if (pShooter->m_Team != m_Team)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bEnemyIsDisguised = false;
|
|
|
|
|
|
|
|
if (pTarget)
|
|
|
|
{
|
|
|
|
if (DoesTheoreticPathExist(pShooter->origin, fDist * 1.5) || CanSee(pTarget, 0, 0.828 * world->farplane_distance, false))
|
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, pTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::NoticeFootstep
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor should notice this footstep sound (pedestrian is not visible for actor).
|
|
|
|
Otherwise returns false.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::NoticeFootstep
|
|
|
|
(
|
|
|
|
Sentient *pPedestrian
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_Team == pPedestrian->m_Team || pPedestrian->m_bIsDisguised)
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return !CanSeeFOV(pPedestrian);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::NoticeVoice
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor should notice this voice sound (vocalist is not visible for actor).
|
|
|
|
Otherwise returns false.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::NoticeVoice
|
|
|
|
(
|
|
|
|
Sentient *pVocallist
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (IsSquadMate(pVocallist))
|
|
|
|
return false;
|
2018-08-02 15:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return !CanSeeFOV(pVocallist);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::ValidGrenadePath
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if grenade trajectory is valid.
|
|
|
|
i.e grenade can get from vFrom to vTo with vVel with any obstacles.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::ValidGrenadePath
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo,
|
|
|
|
Vector& vVel
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
float fGravity, fTime1, fTime2, fTime3, fTimeLand;
|
|
|
|
Vector mins(-4, -4, -4);
|
|
|
|
Vector maxs(4, 4, 4);
|
|
|
|
|
|
|
|
Vector vPoint1, vPoint2, vPoint3;
|
|
|
|
|
|
|
|
if (vVel.lengthSquared() > 589824)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fGravity = 0.8 * sv_gravity->value;
|
|
|
|
|
|
|
|
fTime1 = vVel.z * fGravity / 0.5;
|
|
|
|
|
|
|
|
vPoint1.x = vVel.x * fTime1 + vFrom.x;
|
|
|
|
vPoint1.y = vVel.y * fTime1 + vFrom.y;
|
|
|
|
vPoint1.z = vVel.z * fTime1 * 0.75 + vFrom.z;
|
|
|
|
|
|
|
|
maxs.z = fGravity * 0.125 * fTime1 * fTime1 + 4;
|
|
|
|
|
|
|
|
if (ai_debug_grenades->integer)
|
|
|
|
{
|
|
|
|
G_DebugLine(vFrom, vPoint1, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_SightTrace(vFrom,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint1,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 1"))
|
|
|
|
{
|
|
|
|
fTime2 = fTime1 + fTime1;
|
|
|
|
|
|
|
|
vPoint2.x = vVel.x * fTime2 + vFrom.x;
|
|
|
|
vPoint2.y = vVel.y * fTime2 + vFrom.y;
|
|
|
|
vPoint2.z = vVel.z * fTime2 * 0.5 + vFrom.z;
|
|
|
|
|
|
|
|
if (ai_debug_grenades->integer)
|
|
|
|
{
|
|
|
|
G_DebugLine(vPoint1, vPoint2, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
|
|
|
if (G_SightTrace(vPoint1,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint2,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 2"))
|
|
|
|
{
|
|
|
|
if (fabs(vVel.y) >= fabs(vVel.x))
|
|
|
|
{
|
|
|
|
fTimeLand = (vTo.y - vFrom.y) / vVel.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fTimeLand = (vTo.x - vFrom.x) / vVel.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
fTime3 = (fTime2 + fTimeLand) / 2;
|
|
|
|
maxs.z = fGravity * 0.03125 * (fTimeLand - fTime2) * (fTimeLand - fTime2) + 4;
|
|
|
|
|
|
|
|
|
|
|
|
vPoint3.x = vVel.x * fTime3 + vFrom.x;
|
|
|
|
vPoint3.y = vVel.y * fTime3 + vFrom.y;
|
|
|
|
vPoint3.z = (vVel.z - fGravity * 0.5 * fTime3) * fTime3 + vFrom.z;
|
|
|
|
|
|
|
|
if (ai_debug_grenades->integer)
|
|
|
|
{
|
|
|
|
G_DebugLine(vPoint2, vPoint3, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
|
|
|
if (G_SightTrace(vPoint2,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint3,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 3"))
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ai_debug_grenades->integer)
|
|
|
|
{
|
|
|
|
G_DebugLine(vPoint3, vTo, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
|
|
|
trace_t trace = G_Trace(vPoint3, mins, maxs, vTo, this, 1107569409, qfalse, "Actor::ValidGrenadePath 4");
|
|
|
|
if (!trace.allsolid)
|
|
|
|
{
|
|
|
|
if (trace.ent)
|
|
|
|
{
|
|
|
|
if (trace.ent->entity->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
Sentient *sen = (Sentient *)trace.ent->entity;
|
|
|
|
if (sen->m_Team != m_Team)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(trace.entityNum == 1022 && trace.plane.normal[2] >= 1)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2019-06-25 01:17:10 +02:00
|
|
|
}
|
2019-08-13 03:12:07 +02:00
|
|
|
|
|
|
|
/*
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
Actor::CalcThrowVelocity
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Calculates required grenade throw velocity to get grenade from vFrom to vTo.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::CalcThrowVelocity
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector ret;
|
|
|
|
Vector vDelta;
|
|
|
|
float v10; // ST0C_4
|
|
|
|
float v11; // fst3
|
|
|
|
//////
|
|
|
|
float fGravity;
|
|
|
|
float fVelHorz;
|
|
|
|
float fVelVert;
|
|
|
|
float fDeltaZ;
|
|
|
|
float fDistance;
|
|
|
|
float fHorzDistSquared;
|
|
|
|
float fOOTime;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fGravity = 0.8 * sv_gravity->value;
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vDelta = vTo - vFrom;
|
2019-06-25 01:17:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fVelHorz = vDelta.x;
|
|
|
|
fVelVert = vDelta.y;
|
|
|
|
fDeltaZ = vDelta.z;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fHorzDistSquared = fVelVert * fVelVert + fVelHorz * fVelHorz;
|
2019-06-25 01:17:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fDistance = sqrt(fDeltaZ * fDeltaZ + fHorzDistSquared);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// original irl equation: v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / (fDistance * trigMult ))
|
|
|
|
// trigMult = (cos(th)/ tan(al) - sin(th)/tanSquared(al))
|
|
|
|
// al = inital velocity angle with ground plane.
|
|
|
|
// th = angle between vDelta and ground plane.
|
|
|
|
// mohaa devs decided to let trigMult be 1, for the sake of simplicity I guess.
|
|
|
|
v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / fDistance);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// no I dea what this means.
|
|
|
|
// maybe it's related to their angle choice.
|
|
|
|
// calculates the 1/distanceSquared necessary for fOOTime calculation.
|
|
|
|
v11 = (fDistance + fDeltaZ) / (fDistance - fDeltaZ) / fHorzDistSquared;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// 1/(speed * sqrt(1/distanceSquared))
|
|
|
|
// 1/(speed * 1/distance)
|
|
|
|
// 1/(1/time)
|
|
|
|
// time
|
|
|
|
fOOTime = 1 / (v10 * sqrt(v11));
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ret.z = v10;
|
|
|
|
ret.x = fVelHorz / fOOTime;
|
|
|
|
ret.y = fVelVert / fOOTime;
|
|
|
|
return ret;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CanThrowGrenade
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns required velocity to throw grenade from vFrom to vTo.
|
|
|
|
Or vec_zero if it's not possible.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::CanThrowGrenade
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vVel = vec_zero;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vVel = CalcThrowVelocity(vFrom, vTo);
|
|
|
|
if ( vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel))
|
|
|
|
{
|
|
|
|
return vec_zero;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return vVel;
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CalcRollVelocity
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Calculates required grenade roll velocity to get grenade from vFrom to vTo.
|
|
|
|
Roll here means a low toss.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::CalcRollVelocity
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fOOTime, fVelVert, fVelHorz, fGravity;
|
|
|
|
Vector vDelta = vFrom - vTo, vRet;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// you must throw from above.
|
|
|
|
// start point must be above (higher) than end point.
|
|
|
|
if (vDelta.z > 0)
|
|
|
|
{
|
|
|
|
fGravity = 0.8 * sv_gravity->value;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// Required down velocity to hit the ground twice as fast as freefall time.
|
|
|
|
vRet.z = sqrt(vDelta.z * fGravity);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
// accel = speed / time, hence : time = speed / accel, 0.21961521 is an arbitary scalar.
|
|
|
|
// since the scalar is way less than 1, it will take more time to hit the ground than to arrive to target dest.
|
|
|
|
// this is kinda like a low toss rather than a roll. if I understand correctly.
|
|
|
|
fOOTime = vRet.z / fGravity * 0.21961521;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
// speed = distance / time
|
|
|
|
vRet.x = fVelHorz = -vDelta.x / fOOTime;
|
|
|
|
vRet.y = fVelVert = -vDelta.y / fOOTime;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return vec_zero;
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CanRollGrenade
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns required velocity to roll grenade from vFrom to vTo.
|
|
|
|
Or vec_zero if it's not possible.
|
|
|
|
Roll here means a low toss.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::CanRollGrenade
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vVel = vec_zero;
|
|
|
|
vVel = CalcRollVelocity(vFrom, vTo);
|
|
|
|
if (vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel))
|
|
|
|
{
|
|
|
|
return vec_zero;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return vVel;
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CanTossGrenadeThroughHint
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can toss grenade through specified hint.
|
|
|
|
pvVel and peMode are modified.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::CanTossGrenadeThroughHint
|
|
|
|
(
|
|
|
|
GrenadeHint *pHint,
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo,
|
|
|
|
bool bDesperate,
|
|
|
|
Vector *pvVel,
|
|
|
|
eGrenadeTossMode *peMode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fGravity = 0.8 * sv_gravity->value;
|
|
|
|
float fAngle, fTemp, fTemp2, fTemp3, fTemp4, /*fVelVert, fVelHorz,*/ fRange, fRangeSquared, fDist, fDistSquared, fHeight;
|
|
|
|
bool bSuccess = false;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vDelta, vHintDelta;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!bDesperate)
|
|
|
|
{
|
|
|
|
vHintDelta = pHint->origin - vFrom;
|
|
|
|
vDelta = vFrom - vTo;
|
|
|
|
|
|
|
|
fDist = vDelta.lengthXY();
|
|
|
|
fDistSquared = fDist * fDist;
|
2019-06-25 01:17:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fRange = vHintDelta.z * fDist - vDelta.z * vHintDelta.lengthXY();
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fRange == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fTemp4 = 1 / fRange;
|
|
|
|
fRange = (fDist - vHintDelta.lengthXY()) / fRange;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fRange <= 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fTemp = sqrt(fRange * (fDist * (fGravity * 0.5 * vHintDelta.lengthXY())));
|
|
|
|
fTemp2 = (vHintDelta.z * fDistSquared - vDelta.z * vHintDelta.lengthXYSquared()) * fGravity * 0.5;
|
|
|
|
fTemp3 = fTemp / vHintDelta.lengthXY();
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
pvVel->x = vHintDelta.x * fTemp3;
|
|
|
|
pvVel->y = vHintDelta.y * fTemp3;
|
|
|
|
pvVel->z = 0.5 * fTemp2 / fTemp * fTemp4;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
*peMode = AI_GREN_TOSS_HINT;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return ValidGrenadePath(vFrom, pHint->origin, *pvVel);
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vHintDelta = pHint->origin - vFrom;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fRange = vHintDelta.lengthXY();
|
|
|
|
fRangeSquared = fRange * fRange;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fRangeSquared != 0)
|
|
|
|
{
|
|
|
|
fDist = vHintDelta.length();
|
|
|
|
fHeight = fRangeSquared * fGravity / 589824.0 + vHintDelta.z;
|
|
|
|
if (-fHeight <= -fDist)
|
|
|
|
{
|
|
|
|
fAngle = (atan2(vHintDelta.z / fRangeSquared, 1.0) + atan2(fHeight / fDist, sqrt(1.0 - fHeight / fDist * (fHeight / fDist)))) / 2;
|
|
|
|
pvVel->x = vHintDelta.x * 768.0 / fRangeSquared * cos(fAngle);
|
|
|
|
pvVel->y = vHintDelta.y * 768.0 / fRangeSquared * cos(fAngle);
|
|
|
|
pvVel->z = 768.0 * cos(fAngle);
|
|
|
|
return ValidGrenadePath(vFrom, pHint->origin, *pvVel);
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return bSuccess;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::GrenadeThrowPoint
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns real grenade throw point.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::GrenadeThrowPoint
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vDelta,
|
|
|
|
const_str csAnim
|
|
|
|
)
|
|
|
|
{
|
|
|
|
vec2_t axis;
|
|
|
|
Vector vRet;
|
|
|
|
|
|
|
|
VectorCopy2D(vDelta, axis);
|
|
|
|
VectorNormalize2D(axis);
|
|
|
|
|
|
|
|
if (csAnim == STRING_ANIM_GRENADEKICK_SCR)
|
|
|
|
{
|
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 8;
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (csAnim > STRING_ANIM_GRENADEKICK_SCR)
|
|
|
|
{
|
|
|
|
if (csAnim != STRING_ANIM_GRENADETHROW_SCR && csAnim != STRING_ANIM_GRENADETOSS_SCR)
|
|
|
|
{
|
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 80;
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vRet.x = vFrom.x - axis[0] * 34 + axis[1] * 8;
|
|
|
|
vRet.y = vFrom.y - axis[0] * 8 - axis[1] * 34;
|
|
|
|
vRet.z = 52 + vFrom.z;
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (csAnim != STRING_ANIM_GRENADERETURN_SCR)
|
|
|
|
{
|
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 80;
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
vRet.x = vFrom.x + axis[0] * 25 + axis[1] * 2;
|
|
|
|
vRet.y = vFrom.y - axis[0] * 2 + axis[1] * 25;
|
|
|
|
vRet.z = 89 + vFrom.z;
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CalcKickVelocity
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Calculates required grenade kick velocity.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::CalcKickVelocity
|
|
|
|
(
|
|
|
|
Vector& vDelta,
|
|
|
|
float fDist
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
float fScale, fGravity;
|
|
|
|
Vector ret;
|
|
|
|
float v4;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fGravity = 0.8 * sv_gravity->value;
|
2019-06-25 01:17:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fScale = 0.57735032 * fDist;
|
|
|
|
v4 = sqrt(fGravity * 0.5 / (fScale - vDelta[2]));
|
|
|
|
ret[0] = vDelta[0] * v4;
|
|
|
|
ret[1] = vDelta[1] * v4;
|
|
|
|
ret[2] = fScale * v4;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CanKickGrenade
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can kick grenade from vFrom to vTo.
|
|
|
|
Or false if it's not possible.
|
|
|
|
pvVel is changed.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::CanKickGrenade
|
|
|
|
(
|
|
|
|
Vector &vFrom,
|
|
|
|
Vector &vTo,
|
|
|
|
Vector &vFace,
|
|
|
|
Vector *pvVel
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vEnd, vStart, vDelta, vVel;
|
|
|
|
float fDist, fGravity, fScale;
|
|
|
|
fGravity = sv_gravity->value * 0.8;
|
|
|
|
if (fGravity <= 0.0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vFace, STRING_ANIM_GRENADEKICK_SCR);
|
|
|
|
vDelta = vTo - vStart;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fDist = vDelta.lengthXY();
|
|
|
|
if (vDelta.z >= 0 || Vector::Dot(vDelta, vFace) < 0.0 || fDist < 256 || fDist >= 255401.28 / fGravity + 192.0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fDist < 512)
|
|
|
|
fScale = 192.0 / fDist + 0.25;
|
|
|
|
else
|
|
|
|
fScale = 1.0 - 192.0 / fDist;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vEnd = vStart + vDelta;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vDelta[0] *= fScale;
|
|
|
|
vDelta[1] *= fScale;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
*pvVel = CalcKickVelocity(vDelta, fScale * fDist);
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (*pvVel == vec_zero || !ValidGrenadePath(vStart, vEnd, *pvVel))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2019-08-13 03:12:07 +02:00
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GrenadeWillHurtTeamAt
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if grenade will hurt team at vTo.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::GrenadeWillHurtTeamAt
|
|
|
|
(
|
|
|
|
const Vector& vTo
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_pNextSquadMate == this)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2019-08-13 03:12:07 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
for (Actor * pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this; pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer())
|
|
|
|
{
|
|
|
|
if ((pSquadMate->origin-vTo).length() <= 65536)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::CanGetGrenadeFromAToB
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor can get a grenade from vFrom to vTo.
|
|
|
|
pvVel is the kick/roll/throw velocity.
|
|
|
|
peMode is the possible toss mode.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanGetGrenadeFromAToB
|
|
|
|
(
|
|
|
|
const Vector& vFrom,
|
|
|
|
const Vector& vTo,
|
|
|
|
bool bDesperate,
|
|
|
|
Vector *pvVel,
|
|
|
|
eGrenadeTossMode *peMode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fDot;
|
|
|
|
Vector vHint;
|
|
|
|
Vector vStart;
|
|
|
|
Vector vAxisY;
|
|
|
|
Vector vAxisX;
|
|
|
|
Vector vDelta;
|
|
|
|
Vector vDelta2 = vec_zero;
|
|
|
|
int nHints;
|
|
|
|
GrenadeHint *apHint[4];
|
|
|
|
float fRangeSquared;
|
|
|
|
|
|
|
|
if (sv_gravity->value <= 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
vDelta = vTo - vFrom;
|
|
|
|
fRangeSquared = vDelta.lengthSquared();
|
|
|
|
|
|
|
|
//range < 256
|
|
|
|
if (fRangeSquared < Square(256))
|
|
|
|
return false;
|
|
|
|
if (bDesperate)
|
|
|
|
{
|
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADERETURN_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
//range < 32
|
|
|
|
if (fRangeSquared < Square(1024))
|
|
|
|
{
|
|
|
|
if (!bDesperate)
|
|
|
|
{
|
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pvVel = CanRollGrenade(vStart, vTo);
|
|
|
|
|
|
|
|
if (*pvVel != vec_zero)
|
|
|
|
{
|
|
|
|
*peMode = AI_GREN_TOSS_ROLL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bDesperate)
|
|
|
|
{
|
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pvVel = CanThrowGrenade(vStart, vTo);
|
|
|
|
|
|
|
|
if (*pvVel != vec_zero)
|
|
|
|
{
|
|
|
|
*peMode = AI_GREN_TOSS_THROW;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bDesperate)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nHints = GrenadeHint::GetClosestSet(apHint, 4, vStart, Square(1024));
|
|
|
|
|
|
|
|
for (int i = 0; i <= nHints; i++)
|
|
|
|
{
|
|
|
|
if (bDesperate)
|
|
|
|
{
|
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADERETURN_SCR);
|
|
|
|
if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode))
|
|
|
|
return true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
vHint = apHint[i]->origin;
|
|
|
|
vDelta2 = vHint - vFrom;
|
|
|
|
|
|
|
|
fDot = DotProduct2D(vDelta2, vDelta);
|
|
|
|
if (fDot >= 0 && fDot * fDot <= vDelta.lengthXYSquared() * vDelta2.lengthXYSquared() * 0.89999998)
|
|
|
|
{
|
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADETOSS_SCR);
|
|
|
|
if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*peMode = AI_GREN_TOSS_NONE;
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::DecideToThrowGrenade
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Returns true if actor will throw grenade to vTo.
|
|
|
|
pvVel is the kick/roll/throw velocity.
|
|
|
|
peMode is the toss mode.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::DecideToThrowGrenade
|
|
|
|
(
|
|
|
|
const Vector& vTo,
|
|
|
|
Vector *pvVel,
|
|
|
|
eGrenadeTossMode *peMode
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (Sentient::AmmoCount("grenade"))
|
|
|
|
{
|
|
|
|
if (!GrenadeWillHurtTeamAt(vTo))
|
|
|
|
{
|
|
|
|
return CanGetGrenadeFromAToB(origin, vTo, false, pvVel, peMode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::GenericGrenadeTossThink
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Called when actor in grenade state.
|
|
|
|
i.e. actor noticed a grenade and must think fast.
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::GenericGrenadeTossThink
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vGrenadeVel = vec_zero;
|
|
|
|
eGrenadeTossMode eGrenadeMode;
|
|
|
|
|
|
|
|
if (m_Enemy && level.inttime >= m_iStateTime + 200)
|
|
|
|
{
|
|
|
|
if (CanGetGrenadeFromAToB(
|
|
|
|
origin,
|
|
|
|
m_Enemy->velocity - m_Enemy->origin,
|
|
|
|
false,
|
|
|
|
&vGrenadeVel,
|
|
|
|
&eGrenadeMode))
|
|
|
|
{
|
|
|
|
m_vGrenadeVel = vGrenadeVel;
|
|
|
|
m_eGrenadeMode = eGrenadeMode;
|
|
|
|
}
|
|
|
|
m_iStateTime = level.inttime;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYawDir(m_vGrenadeVel);
|
|
|
|
ContinueAnimation();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor::Grenade_EventFire
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Throw grenade animation
|
2018-09-17 23:50:38 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::Grenade_EventFire
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
const_str csAnim;
|
|
|
|
str strGrenade;
|
|
|
|
float speed;
|
|
|
|
Vector pos, dir, vStart;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.Tag_NumForName(edict->tiki, "tag_weapon_right");
|
|
|
|
|
|
|
|
if (m_eGrenadeMode == AI_GREN_TOSS_ROLL)
|
|
|
|
{
|
|
|
|
csAnim = STRING_ANIM_GRENADETHROW_SCR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
csAnim = STRING_ANIM_GRENADETOSS_SCR;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(origin, orientation[0], csAnim);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = m_vGrenadeVel;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
speed = VectorNormalize(dir);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_Team == TEAM_AMERICAN)
|
|
|
|
{
|
|
|
|
strGrenade = "models/projectiles/M2FGrenade.tik";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strGrenade = "models/projectiles/steilhandgranate.tik";
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ProjectileAttack(vStart, dir, this, strGrenade, 0, speed);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
UseAmmo("grenade", 1);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetTurret
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Listener *l = ev->GetListener(1);
|
|
|
|
if (l && l->inheritsFrom(&TurretGun::ClassInfo))
|
|
|
|
{
|
|
|
|
m_pTurret = (TurretGun *)l;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetTurret
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddListener(m_pTurret);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetAmmoGrenade
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(AmmoCount("grenade"));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetAmmoGrenade
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GiveAmmo("grenade", ev->GetInteger(1));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventEnableEnemy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDesiredEnableEnemy = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventEnablePain
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bEnablePain = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventActivate
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bPatrolWaitTrigger = false;
|
|
|
|
Unregister(STRING_TRIGGER);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventInterruptPoint
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
|
|
|
if (func->PostShoot)
|
|
|
|
(this->*func->PostShoot)();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventAnimScript
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
|
|
|
m_csAnimScript = ev->GetConstString(1);
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
|
|
|
m_AnimMode = 1;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventAnimScript_Scripted
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
|
|
|
m_csAnimScript = ev->GetConstString(1);
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
|
|
|
m_AnimMode = 5;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventAnimScript_Noclip
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
|
|
|
m_csAnimScript = ev->GetConstString(1);
|
|
|
|
//FIXME: macro
|
|
|
|
m_AnimMode = 6;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventReload_mg42
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macos/enum
|
|
|
|
if (m_State != 1201)
|
|
|
|
{
|
|
|
|
if (m_State == 1200)
|
|
|
|
{
|
|
|
|
m_bAnimScriptSet = true;
|
|
|
|
TransitionState(1201, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Unregister(STRING_ANIMDONE);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::CanMovePathWithLeash
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2_t delta;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if( PathExists() )
|
|
|
|
{
|
|
|
|
delta[ 0 ] = origin[ 0 ] - m_vHome[ 0 ];
|
|
|
|
delta[ 1 ] = origin[ 1 ] - m_vHome[ 1 ];
|
|
|
|
|
|
|
|
return ( VectorLength2DSquared( delta ) < m_fLeashSquared ) || ( DotProduct2D( delta, m_Path.CurrentDelta() ) < 0.0f );
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::MovePathWithLeash
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if( CanMovePathWithLeash() )
|
|
|
|
{
|
|
|
|
Anim_RunToInOpen( 2 );
|
|
|
|
FaceMotion();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Anim_Aim();
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector Actor::GunTarget
|
|
|
|
(
|
|
|
|
bool bNoCollision
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float accuracy;
|
|
|
|
static bool doInit = true;
|
|
|
|
static cvar_t *aiRanges[4];
|
|
|
|
Vector vRet;
|
|
|
|
|
|
|
|
if (doInit)
|
|
|
|
{
|
|
|
|
aiRanges[0] = gi.Cvar_Get("g_aishortrange", "500", 0);
|
|
|
|
aiRanges[1] = gi.Cvar_Get("g_aimediumrange", "700", 0);
|
|
|
|
aiRanges[2] = gi.Cvar_Get("g_ailongrange", "1000", 0);
|
|
|
|
aiRanges[3] = gi.Cvar_Get("g_aisniperrange", "2200", 0);
|
|
|
|
doInit = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mTargetPos == vec_zero)
|
|
|
|
{
|
|
|
|
AnglesToAxis(origin, orientation);
|
|
|
|
vRet = Vector(orientation[0]) * 2048 + EyePosition();
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
float scatterMult = 1;
|
|
|
|
|
|
|
|
Player *player = NULL;
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
if (m_Enemy->IsSubclassOfPlayer())
|
|
|
|
{
|
|
|
|
player = (Player *)m_Enemy.Pointer();
|
|
|
|
|
|
|
|
|
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
Vector dir;
|
|
|
|
dir = player->centroid - centroid;
|
|
|
|
|
|
|
|
if (weap)
|
|
|
|
{
|
|
|
|
|
|
|
|
MPrintf("WEAPON RANGE: %f dist: %f\n", aiRanges[weap->mAIRange]->value, dir.length());
|
|
|
|
scatterMult = dir.length() / aiRanges[weap->mAIRange]->value;
|
|
|
|
if (dir.length() > aiRanges[weap->mAIRange]->value)
|
|
|
|
{
|
|
|
|
if (scatterMult > 1)
|
|
|
|
{
|
|
|
|
accuracy = mAccuracy / scatterMult;
|
|
|
|
}
|
|
|
|
MPrintf("OUT OF RANGE - scatterMult: %f\n", scatterMult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"ERROR Actor::GunTarget without a weapon\\n\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (fabs(m_Enemy->origin[2] - origin[2]) >= 128)
|
|
|
|
{
|
|
|
|
scatterMult = 0.5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (random2() > accuracy)
|
|
|
|
{
|
|
|
|
MPrintf("MISS - scatterMult: %f\n", scatterMult);
|
|
|
|
|
|
|
|
if (player)
|
|
|
|
{
|
|
|
|
static cvar_t *scatterHeight;
|
|
|
|
static cvar_t *scatterWide;
|
|
|
|
static bool doInitScatters = false;
|
|
|
|
int lastTrail;
|
|
|
|
|
|
|
|
lastTrail = player->mCurTrailOrigin - 1;
|
|
|
|
if (lastTrail < 0)
|
|
|
|
lastTrail = 1;
|
|
|
|
|
|
|
|
vRet = player->mvTrail[lastTrail];
|
|
|
|
//continue here:
|
|
|
|
//Player *tPlayer = player + 12*lastTrail;//weird
|
|
|
|
if (!G_SightTrace(GunPosition(), vec_zero, vec_zero, player->mvTrail[lastTrail], this, player, 33819417, 0, "Actor::GunTarget 1"))
|
|
|
|
{
|
|
|
|
vRet = player->mvTrailEyes[lastTrail];
|
|
|
|
}
|
|
|
|
if (!doInitScatters)
|
|
|
|
{
|
|
|
|
scatterWide = gi.Cvar_Get("g_aiScatterWide", "16.0", 0);
|
|
|
|
scatterHeight = gi.Cvar_Get("g_aiScatterHeight", "45.0", 0);
|
|
|
|
doInitScatters = true;
|
|
|
|
}
|
|
|
|
vRet.x += crandom() * scatterWide->value * scatterMult;
|
|
|
|
vRet.y += crandom() * scatterWide->value * scatterMult;
|
|
|
|
vRet.z += crandom() * scatterHeight->value * scatterMult;
|
|
|
|
|
|
|
|
if (player && player->GetVehicleTank())
|
|
|
|
{
|
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int sign;
|
|
|
|
|
|
|
|
if (random() > 0.5)
|
|
|
|
sign = 1;
|
|
|
|
else
|
|
|
|
sign = -1;
|
|
|
|
vRet.x = sign * 32 * (random() + 1);
|
|
|
|
|
|
|
|
if (random() > 0.5)
|
|
|
|
sign = 1;
|
|
|
|
else
|
|
|
|
sign = -1;
|
|
|
|
vRet.y = sign * 32 * (random() + 1);
|
|
|
|
|
|
|
|
if (random() > 0.5)
|
|
|
|
sign = 1;
|
|
|
|
else
|
|
|
|
sign = -1;
|
|
|
|
vRet.z = sign * 48 * (random() + 1);
|
|
|
|
|
|
|
|
vRet += mTargetPos;
|
|
|
|
|
|
|
|
if (player && player->GetVehicleTank())
|
|
|
|
{
|
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPrintf("HIT\n");
|
|
|
|
|
|
|
|
if (player)
|
|
|
|
{
|
|
|
|
vRet = player->centroid;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vRet = mTargetPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
if (!G_SightTrace(GunPosition(), vec_zero, vec_zero, vRet, this, m_Enemy, 33819417, qfalse, "Actor::GunTarget 1"))
|
|
|
|
{
|
|
|
|
vRet = EyePosition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (player && player->GetVehicleTank())
|
|
|
|
{
|
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
|
|
|
return vRet;
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
qboolean Actor::setModel
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
str headModel, headSkin, weapon;
|
|
|
|
headModel = level.GetRandomHeadModel(model);
|
|
|
|
headSkin = level.GetRandomHeadSkin(model);
|
|
|
|
//qboolean bSuccess;
|
|
|
|
str name = "", tempstr;
|
|
|
|
|
|
|
|
if (model != "")
|
|
|
|
{
|
|
|
|
if (m_csLoadOut != STRING_EMPTY)
|
|
|
|
{
|
|
|
|
|
|
|
|
name = "weapon|" + Director.GetString(m_csLoadOut) + "|";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_csHeadModel == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
m_csHeadModel = Director.AddString(level.GetRandomHeadModel(model));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_csHeadModel != STRING_EMPTY)
|
|
|
|
{
|
|
|
|
name += "headmodel|" + Director.GetString(m_csHeadModel) + "|";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_csHeadSkin == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
m_csHeadSkin = Director.AddString(level.GetRandomHeadSkin(model));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_csHeadSkin != STRING_EMPTY)
|
|
|
|
{
|
|
|
|
name += "headskin|" + Director.GetString(m_csHeadSkin) + "|";//FIXME: not sure of this last "|"
|
|
|
|
}
|
|
|
|
name += model;
|
|
|
|
}
|
|
|
|
gi.DPrintf2("Actor::setModel(): name: %s, model: %s, headModel: %s, headSkin: %s\n", name.c_str(), model.c_str(), headModel.c_str(), headSkin.c_str());
|
|
|
|
level.skel_index[edict->s.number] = -1;
|
|
|
|
return gi.setmodel(edict, name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetHeadModel
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csHeadModel = ev->GetConstString(1);
|
|
|
|
setModel();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetHeadModel
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csHeadModel);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetHeadSkin
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csHeadSkin = ev->GetConstString(1);
|
|
|
|
setModel();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetHeadSkin
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csHeadSkin);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetPathWithLeash
|
|
|
|
(
|
|
|
|
Vector vDestPos,
|
|
|
|
const char *description,
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
|
|
|
{
|
|
|
|
vec2_t dist = { vDestPos[0] - m_vHome[0], vDestPos[1] - m_vHome[1] };
|
|
|
|
float distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared)
|
|
|
|
{
|
|
|
|
dist[0] = origin[0] - m_vHome[0];
|
|
|
|
dist[1] = origin[1] - m_vHome[1];
|
|
|
|
distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared)
|
|
|
|
{
|
|
|
|
SetPath(
|
|
|
|
vDestPos,
|
|
|
|
description,
|
|
|
|
iMaxDirtyTime,
|
|
|
|
m_vHome,
|
|
|
|
m_fLeashSquared);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ClearPath();
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::SetPathWithLeash
|
|
|
|
(
|
|
|
|
SimpleEntity *pDestNode,
|
|
|
|
const char *description,
|
|
|
|
int iMaxDirtyTime
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (pDestNode)
|
|
|
|
{
|
|
|
|
SetPathWithLeash(
|
|
|
|
pDestNode->origin,
|
|
|
|
description,
|
|
|
|
iMaxDirtyTime);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_bPathErrorTime + 5000 < level.inttime)
|
|
|
|
{
|
|
|
|
m_bPathErrorTime = level.inttime;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ No destination node specified for '%s' at (%f %f %f)\n",
|
|
|
|
targetname.c_str(),
|
|
|
|
origin[0],
|
|
|
|
origin[1],
|
|
|
|
origin[2]);
|
|
|
|
}
|
|
|
|
ClearPath();
|
|
|
|
}
|
|
|
|
}
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FindPathAwayWithLeash
|
|
|
|
(
|
|
|
|
vec3_t vAwayFrom,
|
|
|
|
vec3_t vDirPreferred,
|
|
|
|
float fMinSafeDist
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_Path.FindPathAway(
|
|
|
|
origin,
|
|
|
|
vAwayFrom,
|
|
|
|
vDirPreferred,
|
|
|
|
this,
|
|
|
|
fMinSafeDist,
|
|
|
|
m_vHome,
|
|
|
|
m_fLeashSquared);
|
|
|
|
ShortenPathToAvoidSquadMates();
|
|
|
|
}
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::FindPathNearWithLeash
|
|
|
|
(
|
|
|
|
vec3_t vNearbyTo,
|
|
|
|
float fCloseDistSquared
|
|
|
|
)
|
|
|
|
{
|
|
|
|
vec2_t dist = {vNearbyTo[0] - m_vHome[0], vNearbyTo[1] - m_vHome[1]};
|
|
|
|
float distSq = DotProduct2D(dist,dist);
|
|
|
|
|
|
|
|
if (distSq <= m_fLeashSquared + fCloseDistSquared + 2 * sqrt(m_fLeashSquared * fCloseDistSquared))
|
|
|
|
{
|
|
|
|
dist[0] = origin[0] - m_vHome[0];
|
|
|
|
dist[1] = origin[1] - m_vHome[1];
|
|
|
|
distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared)
|
|
|
|
{
|
|
|
|
m_Path.FindPathNear(
|
|
|
|
origin,
|
|
|
|
vNearbyTo,
|
|
|
|
this,
|
|
|
|
0,
|
|
|
|
fCloseDistSquared,
|
|
|
|
m_vHome,
|
|
|
|
m_fLeashSquared);
|
|
|
|
ShortenPathToAvoidSquadMates();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::GetAntiBunchPoint
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
|
|
|
Vector Actor::GetAntiBunchPoint
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
Vector ret = vec_origin;
|
|
|
|
if (m_pNextSquadMate != this)
|
|
|
|
{
|
|
|
|
for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate)
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector dist = origin - pSquadMate->origin;
|
|
|
|
float distSq = dist * dist;
|
|
|
|
if (distSq != 0)
|
|
|
|
{
|
|
|
|
if (Square(m_fInterval) > distSq)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
ret += origin + (dist/sqrt(distSq)) * (m_fInterval - sqrt(distSq));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count)
|
|
|
|
{
|
|
|
|
if (count != 1)
|
|
|
|
{
|
|
|
|
ret /= count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = origin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::AutoArchiveModel
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::AddToBodyQue
|
|
|
|
|
|
|
|
Add this to body queue.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::AddToBodyQue
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
SafePtr<Actor> lastActor = mBodyQueue[mCurBody + 3];
|
|
|
|
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (lastActor)
|
|
|
|
{
|
|
|
|
Event ev(EV_Remove);
|
|
|
|
lastActor->PostEvent(ev, 0);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
mBodyQueue[mCurBody] = this;
|
|
|
|
|
|
|
|
//update current body index
|
|
|
|
mCurBody = (mCurBody + 1) % 5;
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::ResetBodyQueue
|
|
|
|
|
|
|
|
Clear body queue.
|
|
|
|
Called upon Level::Cleanup()
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::ResetBodyQueue
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//weird useless loop ?
|
|
|
|
|
|
|
|
for (int i = MAX_BODYQUEUE-1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
//do nothing.
|
|
|
|
}
|
|
|
|
//mBodyQueue
|
|
|
|
//this resets curBody, but all the magic happens in AddToBodyQue
|
|
|
|
mCurBody = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetNoIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNoIdleAfterAnim = ev->GetInteger(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetNoIdle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bNoIdleAfterAnim);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetEnemy
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddListener(m_Enemy);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetMaxNoticeTimeScale
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float noticeScale; // fst7
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
noticeScale = ev->GetFloat(1);
|
|
|
|
if (noticeScale <= 0.0)
|
|
|
|
{
|
|
|
|
Com_Printf("^~^~^ ERROR: noticescale: value must be greater than 0\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_fMaxNoticeTimeScale = noticeScale / 100;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetMaxNoticeTimeScale
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
ev->AddFloat(m_fMaxNoticeTimeScale * 100);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetFixedLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bFixedLeash = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetFixedLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bFixedLeash);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::Holster
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (activeWeaponList[0])
|
|
|
|
{
|
|
|
|
DeactivateWeapon(WEAPON_MAIN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::Unholster
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Weapon *weap;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!activeWeaponList[0])
|
|
|
|
{
|
|
|
|
weap = GetWeapon(WEAPON_MAIN);
|
|
|
|
if (weap)
|
|
|
|
{
|
|
|
|
useWeapon(weap, WEAPON_MAIN);
|
|
|
|
ActivateNewWeapon();
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
void Actor::EventHolster
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
if (activeWeaponList[WEAPON_MAIN])
|
|
|
|
{
|
|
|
|
DeactivateWeapon(WEAPON_MAIN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventUnholster
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Unholster();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventIsEnemyVisible
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bEnemyVisible);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetEnemyVisibleChangeTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: /100 ??
|
|
|
|
ev->AddFloat(m_iEnemyVisibleChangeTime / 100);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetLastEnemyVisibleTime
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: /100 ??
|
|
|
|
ev->AddFloat(m_iLastEnemyVisibleTime / 100 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSoundDone
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//soundChannel_t
|
|
|
|
int channel = ev->GetInteger(1);
|
|
|
|
str name = ev->GetString(2);
|
|
|
|
if (gi.S_IsSoundPlaying(channel, name))
|
|
|
|
{
|
|
|
|
Event e1(EV_SoundDone);
|
|
|
|
e1.AddInteger(channel);
|
|
|
|
e1.AddString(name);
|
|
|
|
PostEvent(e1, level.frametime);
|
|
|
|
}
|
|
|
|
else if (m_bSayAnimSet && m_iSaySlot == -2) //FIXME: macro
|
|
|
|
{
|
|
|
|
ChangeSayAnim();
|
|
|
|
if (m_csSayAnim == STRING_EMPTY)
|
|
|
|
{
|
|
|
|
//gi.DPrintf("unregister STRING_SAYDONE\n");
|
|
|
|
Unregister(STRING_SAYDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Unregister(STRING_SOUNDDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSound
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ProcessSoundEvent(ev, m_Team == TEAM_AMERICAN);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetFallHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float fHeight = ev->GetFloat(1);
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fHeight < MIN_FALLHEIGHT)
|
|
|
|
{
|
|
|
|
ScriptError("value less than %d not allowed", MIN_FALLHEIGHT);
|
|
|
|
}
|
|
|
|
if (fHeight > MAX_FALLHEIGHT)
|
|
|
|
{
|
|
|
|
ScriptError("value greater than %d not allowed", MAX_FALLHEIGHT);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.SetFallHeight(fHeight);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetFallHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_Path.GetFallHeight());
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventCanMoveTo
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fIntervalSquared, fDistSquared;
|
|
|
|
vec2_t vDelta;
|
|
|
|
Vector vDest;
|
|
|
|
|
|
|
|
vDest = ev->GetVector(1);
|
|
|
|
VectorSub2D(vDest, m_vHome, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
if (fDistSquared >= m_fLeashSquared)
|
|
|
|
{
|
|
|
|
ev->AddInteger(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(m_Enemy != NULL)
|
|
|
|
{
|
|
|
|
VectorSub2D(vDest, m_Enemy->origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
if (m_fMinDistanceSquared >= fDistSquared || fDistSquared >= m_fMaxDistanceSquared)
|
|
|
|
{
|
|
|
|
ev->AddInteger(qfalse);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_fInterval == 0)
|
|
|
|
{
|
|
|
|
for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this ; pSquadMate = pSquadMate->m_pNextSquadMate)
|
|
|
|
{
|
|
|
|
float v27, v29, v30, v32, v33, v34, v35, v37, v38;
|
|
|
|
if (pSquadMate->IsSubclassOfActor())
|
|
|
|
{
|
|
|
|
Sentient *pEnemy = pSquadMate->m_Enemy;
|
|
|
|
if (pEnemy)
|
|
|
|
{
|
|
|
|
v27 = pSquadMate->origin[0];
|
|
|
|
v29 = pEnemy->origin[0] - v27;
|
|
|
|
v30 = pSquadMate->origin[1];
|
|
|
|
v32 = pEnemy->origin[1] - v30;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v27 = pSquadMate->origin[0];
|
|
|
|
v29 = pSquadMate->orientation[0][0];
|
|
|
|
v32 = pSquadMate->orientation[0][1];
|
|
|
|
v30 = pSquadMate->origin[1];
|
|
|
|
}
|
|
|
|
v33 = v32 * origin[0];
|
|
|
|
v34 = v27 * v32 - v30 * v29;
|
|
|
|
v35 = v33 - v29 * origin[1] - v34;
|
|
|
|
v37 = v32 * vDest[0];
|
|
|
|
v38 = v37 - v29 * vDest[1] - v34;
|
|
|
|
|
|
|
|
// check if they both have different sign.
|
|
|
|
if (((int)v38 ^ (int)v35) < 0)
|
|
|
|
{
|
|
|
|
ev->AddInteger(qfalse);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev->AddInteger(qtrue);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fIntervalSquared = Square(m_fInterval);
|
|
|
|
|
|
|
|
for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate)
|
|
|
|
{
|
|
|
|
Vector vDel;
|
|
|
|
vDel = vDest - pSquadMate->origin;
|
|
|
|
if (fIntervalSquared <= vDest.lengthSquared())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((origin-pSquadMate->origin).lengthSquared() > vDest.lengthSquared())
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev->AddInteger(qfalse);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventMoveDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
vec2_t vec;
|
|
|
|
if (!PathGoalSlowdownStarted())
|
|
|
|
{
|
|
|
|
vec[0] = velocity.x;
|
|
|
|
vec[1] = velocity.y;
|
|
|
|
if ( velocity.x == 0 && velocity.y == 0 && PathExists() && !PathComplete())
|
|
|
|
{
|
|
|
|
vec[0] = PathDelta()[0];
|
|
|
|
vec[1] = PathDelta()[1];
|
|
|
|
}
|
|
|
|
VectorNormalize2D(vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
ev->AddVector(vec);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventIntervalDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
if (level.inttime >= m_iIntervalDirTime + 250)
|
|
|
|
{
|
|
|
|
m_vIntervalDir = vec_zero;
|
|
|
|
m_iIntervalDirTime = level.inttime;
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
m_vIntervalDir = GetAntiBunchPoint() - origin;
|
|
|
|
if (m_vIntervalDir.x != 0 || m_vIntervalDir.y != 0)
|
|
|
|
{
|
|
|
|
VectorNormalizeFast(m_vIntervalDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ev->AddVector(m_vIntervalDir);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventResetLeash
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vHome = origin;
|
|
|
|
//delete m_pTetherEnt;
|
|
|
|
m_pTetherEnt = NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventTether
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pTetherEnt = ev->GetSimpleEntity(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Actor::ShortenPathToAttack
|
|
|
|
(
|
|
|
|
float fMinDist
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (PathExists() && !PathComplete() && PathAvoidsSquadMates())
|
|
|
|
{
|
|
|
|
for (auto current_node = CurrentPathNode(); current_node >= LastPathNode(); current_node--)
|
|
|
|
{
|
|
|
|
Vector dist = current_node->point - origin;
|
|
|
|
if (dist * dist >= fMinDist * fMinDist)
|
|
|
|
{
|
|
|
|
if (CanSeeFrom(eyeposition + current_node->point, m_Enemy))
|
|
|
|
{
|
|
|
|
m_Path.TrimPathFromEnd((current_node - LastPathNode()) / 32);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::StrafeToAttack
|
|
|
|
(
|
|
|
|
float fDist,
|
|
|
|
vec3_t vDir
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vEnemyCentroid, vDelta, vSpot, vDestPos;
|
|
|
|
Vector mins(-16,-16,16);
|
|
|
|
Vector maxs(16,16,128);
|
|
|
|
|
|
|
|
vDestPos = vDir;
|
|
|
|
vDestPos *= fDist;
|
|
|
|
vDestPos += origin;
|
|
|
|
|
|
|
|
vDelta = vDestPos - m_vLastEnemyPos;
|
|
|
|
|
|
|
|
if (m_fMaxDistanceSquared <= vDelta.lengthSquared() || vDelta.lengthSquared() <= m_fMinDistanceSquared )
|
|
|
|
{
|
|
|
|
ClearPath();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!G_SightTrace(
|
|
|
|
origin,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vDestPos,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107437825,
|
|
|
|
qtrue,
|
|
|
|
"Actor::StrafeToAttack 1"))
|
|
|
|
{
|
|
|
|
ClearPath();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vSpot = vDir;
|
|
|
|
vSpot *= fDist;
|
|
|
|
|
|
|
|
vDelta = m_vLastEnemyPos;
|
|
|
|
vDelta.z += m_Enemy->centroid.z - m_Enemy->origin.z;
|
|
|
|
|
|
|
|
if (!G_SightTrace(
|
|
|
|
EyePosition() + vSpot,
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
vDelta,
|
|
|
|
this,
|
|
|
|
m_Enemy,
|
|
|
|
//FIXME: macro
|
|
|
|
33819417,
|
|
|
|
qfalse,
|
|
|
|
"Actor::StrafeToAttack 1"))
|
|
|
|
{
|
|
|
|
SetPathWithLeash(vDestPos, NULL, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ClearPath();
|
|
|
|
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetThinkState
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(m_csThinkStateNames[m_ThinkState]);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetEnemyShareRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fMaxShareDistSquared);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetEnemyShareRange
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float fRange = ev->GetFloat(1);
|
|
|
|
m_fMaxShareDistSquared = fRange * fRange;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::GetVoiceType
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//voice type in actor is a char.
|
|
|
|
const char *vType = va("%c", mVoiceType);
|
|
|
|
str vTypeStr = vType;
|
|
|
|
ev->AddString(vTypeStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::SetVoiceType
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//voice type in actor is a char.
|
|
|
|
str vType = ev->GetString(1);
|
|
|
|
if (vType[0])
|
|
|
|
{
|
|
|
|
mVoiceType = vType[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//FIXME: enum
|
|
|
|
mVoiceType = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PathNode *Actor::FindSniperNodeAndSetPath
|
|
|
|
(
|
|
|
|
bool *pbTryAgain
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PathNode *pSniperNode = PathManager.FindNearestSniperNode( this, origin, m_Enemy );
|
|
|
|
|
|
|
|
if( pSniperNode )
|
|
|
|
{
|
|
|
|
SetPathWithLeash( pSniperNode, NULL, 0 );
|
|
|
|
|
|
|
|
if( PathExists() && ( PathComplete() || PathAvoidsSquadMates() ) )
|
|
|
|
{
|
|
|
|
*pbTryAgain = true;
|
|
|
|
return pSniperNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
pSniperNode->MarkTemporarilyBad();
|
|
|
|
*pbTryAgain = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pbTryAgain = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::Remove
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
EndStates();
|
|
|
|
|
|
|
|
if (deadflag != DEAD_DEAD)
|
|
|
|
{
|
|
|
|
health = 0;
|
|
|
|
deadflag = DEAD_DEAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
Delete();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetKickDir
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddVector(m_vKickDir);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetNoLongPain
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bNoLongPain);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetNoLongPain
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNoLongPain = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DontFaceWall
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//PathNode *pNode;
|
|
|
|
vec2_t vDelta;
|
|
|
|
float /*fErrorLerp,*/ fEyeRadius, fCosAngle, fSinAngle, fAngle, fAngleRad, fTime;
|
|
|
|
Vector start;
|
|
|
|
Vector end;
|
|
|
|
|
|
|
|
//FIXME: macro: AI_*
|
|
|
|
if (m_pCoverNode && m_pCoverNode->nodeflags & (AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE))
|
|
|
|
{
|
|
|
|
m_eDontFaceWallMode = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (velocity.lengthXYSquared() > Square(8))
|
|
|
|
{
|
|
|
|
m_eDontFaceWallMode = 2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fAngle = AngleNormalize360(m_YawAchieved ? angles.y : m_DesiredYaw);
|
|
|
|
|
|
|
|
fTime = (level.time - m_fDfwTime) * 0.5;
|
|
|
|
if (fTime > 1)
|
|
|
|
{
|
|
|
|
fTime = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VectorSub2D(m_vDfwPos, origin, vDelta);
|
|
|
|
|
|
|
|
if (Square(fTime * -14.0 + 16.0) > VectorLength2DSquared(vDelta)
|
|
|
|
&& (fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0
|
|
|
|
|| fabs(AngleNormalize180(m_fDfwDerivedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_eDontFaceWallMode <= 8)
|
|
|
|
{
|
|
|
|
SetDesiredYaw(m_fDfwDerivedYaw);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_vDfwPos = origin;
|
|
|
|
m_fDfwRequestedYaw = fAngle;
|
|
|
|
m_fDfwTime = level.time;
|
|
|
|
|
|
|
|
fAngleRad = fAngle * M_PI / 180;
|
|
|
|
fSinAngle = sin(fAngleRad);
|
|
|
|
fCosAngle = cos(fAngleRad);
|
|
|
|
|
|
|
|
VectorSub2D(EyePosition(), origin, vDelta);
|
|
|
|
fEyeRadius = VectorLength2D(vDelta);
|
|
|
|
|
|
|
|
start = vec_zero;
|
|
|
|
start.x = fEyeRadius * fCosAngle + origin.x;
|
|
|
|
start.y = fEyeRadius * fSinAngle + origin.y;
|
|
|
|
|
|
|
|
end = vec_zero;
|
|
|
|
end.x = 64 * fCosAngle + start.x;
|
|
|
|
end.x = 64 * fSinAngle + start.y;
|
|
|
|
trace_t trace = G_Trace(start, vec_zero, vec_zero, end, this, 33819417, qfalse, "Actor::DontFaceWall");
|
|
|
|
if (trace.entityNum == 1023 || trace.fraction >= 1 || trace.startsolid)
|
|
|
|
{
|
|
|
|
m_eDontFaceWallMode = 3;
|
|
|
|
}
|
|
|
|
else if (trace.entityNum == 1022 || trace.ent->entity->AIDontFace())
|
|
|
|
{
|
|
|
|
if (trace.plane.normal[2] < -0.69999999 || trace.plane.normal[2] > 0.69999999)
|
|
|
|
{
|
|
|
|
m_eDontFaceWallMode = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_Enemy && Vector::Dot(trace.plane.normal, m_Enemy->origin) - trace.plane.dist < 0 )
|
|
|
|
{
|
|
|
|
end = m_Enemy->origin;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end = start + (end - start)*128;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PathNode *node = PathManager.FindCornerNodeForWall(origin, end, this, 0.0f, trace.plane.normal);
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
|
|
|
|
VectorSub2D(node->m_PathPos, origin, vDelta);
|
|
|
|
if (vDelta[0] != 0 || vDelta[1] != 0)
|
|
|
|
{
|
|
|
|
SetDesiredYawDir(vDelta);
|
|
|
|
}
|
|
|
|
m_eDontFaceWallMode = 6;
|
|
|
|
}
|
|
|
|
else if (trace.fraction <= 0.46875)
|
|
|
|
{
|
|
|
|
SetDesiredYawDir(trace.plane.normal);
|
|
|
|
m_eDontFaceWallMode = 7;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_DesiredYaw < 90.0)
|
|
|
|
m_DesiredYaw += 270.0;
|
|
|
|
else
|
|
|
|
m_DesiredYaw -= 90.0;
|
|
|
|
|
|
|
|
m_YawAchieved = false;
|
|
|
|
m_eDontFaceWallMode = 8;
|
|
|
|
}
|
|
|
|
m_fDfwDerivedYaw = m_DesiredYaw;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_eDontFaceWallMode = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fDfwDerivedYaw = m_fDfwRequestedYaw;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Actor::IsVoidState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsIdleState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_IDLE;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsCuriousState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_CURIOUS;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsDisguiseState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_DISGUISE;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsAttackState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_ATTACK;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsGrenadeState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_GRENADE;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsPainState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_PAIN;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::IsKilledState
|
|
|
|
(
|
|
|
|
int state
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return state == THINKSTATE_KILLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::InitVoid
|
|
|
|
|
|
|
|
Init void global func
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::InitVoid
|
|
|
|
(
|
|
|
|
GlobalFuncs_t *func
|
|
|
|
)
|
|
|
|
{
|
|
|
|
func->IsState = &Actor::IsVoidState;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::BecomeCorpse
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Event e1(EV_DeathSinkStart);
|
|
|
|
|
|
|
|
AddToBodyQue();
|
|
|
|
|
|
|
|
edict->r.contents = CONTENTS_TRIGGER;
|
|
|
|
edict->r.svFlags &= ~SVF_MONSTER;
|
|
|
|
setSolidType(SOLID_NOT);
|
|
|
|
movetype = MOVETYPE_NONE;
|
|
|
|
edict->s.renderfx &= ~RF_SHADOW;
|
|
|
|
|
|
|
|
|
|
|
|
PostEvent(e1, 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetFavoriteEnemy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddEntity(m_FavoriteEnemy);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetFavoriteEnemy
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Sentient *fEnemy = (Sentient*)ev->GetEntity(1);
|
|
|
|
m_FavoriteEnemy = fEnemy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetMumble
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddInteger(m_bMumble);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetMumble
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_bMumble = ev->GetInteger(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventCalcGrenadeToss
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
Vector vTarget;
|
|
|
|
vTarget = ev->GetVector(1);
|
|
|
|
if (DecideToThrowGrenade(vTarget, &m_vGrenadeVel, &m_eGrenadeMode))
|
|
|
|
{
|
|
|
|
if (m_eGrenadeMode == AI_GREN_TOSS_ROLL)
|
|
|
|
{
|
|
|
|
ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_eGrenadeMode > AI_GREN_TOSS_ROLL ? m_eGrenadeMode == AI_GREN_TOSS_HINT : m_eGrenadeMode == AI_GREN_TOSS_THROW)
|
|
|
|
{
|
|
|
|
ev->AddConstString(STRING_ANIM_GRENADETHROW_SCR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char assertStr[16317] = { 0 };
|
|
|
|
strcpy(assertStr, "\"invalid return condition for Actor::EventCalcGrenadeToss\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYawDir(m_vGrenadeVel);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ev->AddConstString(STRING_EMPTY);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetNoSurprise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bNoSurprise);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetNoSurprise
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNoSurprise = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetSilent
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bSilent);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetSilent
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bSilent = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetAvoidPlayer
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bAutoAvoidPlayer);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetAvoidPlayer
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAutoAvoidPlayer = ev->GetBoolean(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::PathnodeClaimRevoked
|
|
|
|
(
|
|
|
|
PathNode *node
|
|
|
|
)
|
|
|
|
{
|
|
|
|
for (int i = m_ThinkLevel; i >= 0; --i)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]];
|
|
|
|
if (func->PathnodeClaimRevoked)
|
|
|
|
(this->*func->PathnodeClaimRevoked)();
|
|
|
|
}
|
|
|
|
node->Relinquish();
|
|
|
|
m_pCoverNode = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::SetPathToNotBlockSentient
|
|
|
|
(
|
|
|
|
Sentient *pOther
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vDest, vPerp, vAway;
|
|
|
|
|
|
|
|
if (pOther)
|
|
|
|
{
|
|
|
|
if (!pOther->IsDead())
|
|
|
|
{
|
|
|
|
if (IsTeamMate(pOther))
|
|
|
|
{
|
|
|
|
if (pOther->velocity.lengthSquared() > 1)
|
|
|
|
{
|
|
|
|
vDest = origin - pOther->origin;
|
|
|
|
if (vDest.lengthSquared() < 2304 && DotProduct2D(pOther->velocity, vDest) > 0)
|
|
|
|
{
|
|
|
|
if (CrossProduct2D(vDest, pOther->velocity) >= 0)
|
|
|
|
{
|
|
|
|
vPerp.x = -pOther->velocity.y;
|
|
|
|
vPerp.y = pOther->velocity.x;
|
|
|
|
vPerp.z = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vPerp.x = pOther->velocity.y;
|
|
|
|
vPerp.y = -pOther->velocity.x;
|
|
|
|
vPerp.z = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorNormalizeFast(vPerp);
|
|
|
|
|
|
|
|
vAway = vPerp * 48 + origin;
|
|
|
|
|
|
|
|
if (G_SightTrace(
|
|
|
|
vAway,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vAway,
|
|
|
|
this,
|
|
|
|
pOther,
|
|
|
|
33557249,
|
|
|
|
0,
|
|
|
|
"Actor::SetPathToNotBlockSentient 1"))
|
|
|
|
{
|
|
|
|
SetPathWithinDistance(vAway, NULL, 96, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PathExists())
|
|
|
|
{
|
|
|
|
vAway = vDest;
|
|
|
|
VectorNormalizeFast(vAway);
|
|
|
|
|
|
|
|
vAway = vAway * 48 + origin;
|
|
|
|
if (G_SightTrace(
|
|
|
|
vAway,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vAway,
|
|
|
|
this,
|
|
|
|
pOther,
|
|
|
|
33557249,
|
|
|
|
0,
|
|
|
|
"Actor::SetPathToNotBlockSentient 2"))
|
|
|
|
{
|
|
|
|
SetPathWithinDistance(vAway, NULL, 96, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PathExists())
|
|
|
|
{
|
|
|
|
vAway = vPerp * 48 - origin;
|
|
|
|
if (G_SightTrace(
|
|
|
|
vAway,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vAway,
|
|
|
|
this,
|
|
|
|
pOther,
|
|
|
|
33557249,
|
|
|
|
0,
|
|
|
|
"Actor::SetPathToNotBlockSentient 3"))
|
|
|
|
{
|
|
|
|
SetPathWithinDistance(vAway, NULL, 96, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PathExists())
|
|
|
|
{
|
|
|
|
vAway = vDest;
|
|
|
|
VectorNormalizeFast(vAway);
|
|
|
|
|
|
|
|
FindPathAway(origin, vAway * 100, 96);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::LookAround
|
|
|
|
|
|
|
|
Look around behaviour.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::LookAround
|
|
|
|
(
|
|
|
|
float fFovAdd
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Vector vDest, vAngle;
|
|
|
|
float fModTime;
|
|
|
|
|
|
|
|
if (level.inttime >= m_iNextLookTime)
|
|
|
|
{
|
|
|
|
fModTime = level.time;
|
|
|
|
vAngle = angles;
|
|
|
|
|
|
|
|
vAngle.y += fFovAdd * (2*(fModTime * 0.125 - floor(fModTime * 0.125)) - 1.0);
|
|
|
|
vAngle.x += (noise1(fModTime * 1.005309626678312 + entnum) + 1.0) * 15.0;
|
|
|
|
|
|
|
|
AngleVectors(vAngle, vDest, NULL, NULL);
|
|
|
|
|
|
|
|
vDest += EyePosition() * 1024;
|
|
|
|
trace_t trace = G_Trace(EyePosition(), vec_zero, vec_zero, vDest, this, 25, qfalse, "Actor::LookAround");
|
|
|
|
if (trace.fraction > 0.125)
|
|
|
|
{
|
|
|
|
m_bHasDesiredLookDest = true;
|
|
|
|
VectorCopy(trace.endpos, m_vDesiredLookDest);
|
|
|
|
m_iNextLookTime = level.inttime + rand() % 500 + 750;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bHasDesiredLookDest = false;
|
|
|
|
m_iNextLookTime = level.inttime + 187;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_bHasDesiredLookDest)
|
|
|
|
{
|
|
|
|
SetDesiredLookDir(m_vDesiredLookDest - EyePosition());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetLookAroundAngle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: weird
|
|
|
|
//ev->GetFloat(m_fLookAroundFov);
|
|
|
|
ev->AddFloat(m_fLookAroundFov);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetLookAroundAngle
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float angle = ev->GetFloat(1);
|
|
|
|
if (angle < 0.0 || angle > 60.0)
|
|
|
|
{
|
|
|
|
ScriptError("lookaroundangle must be >= 0 and <= 60");
|
|
|
|
}
|
|
|
|
m_fLookAroundFov = angle;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::DumpAnimInfo
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Animate::DumpAnimInfo();
|
|
|
|
Vector desiredLook = m_bHasDesiredLookAngles ? m_DesiredLookAngles : vec_zero;
|
|
|
|
//FIXME: macros: bones
|
|
|
|
Vector head = GetControllerAngles(HEAD_TAG);
|
|
|
|
Vector torso = GetControllerAngles(TORSO_TAG);
|
|
|
|
MPrintf("Desired look yaw: %.1f, pitch: %.1f. Head yaw: %.1f, pitch %.1f. Torso yaw: %.1f, pitch: %.1f\n",
|
|
|
|
desiredLook.x,
|
|
|
|
desiredLook.y,
|
|
|
|
head.x,
|
|
|
|
head.y,
|
|
|
|
torso.x,
|
|
|
|
torso.y
|
|
|
|
);
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::DumpCallTrace
|
|
|
|
|
|
|
|
Dump useful debug info.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
const char *Actor::DumpCallTrace
|
|
|
|
(
|
|
|
|
const char *pszFmt,
|
|
|
|
...
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
cvar_t *sv_mapname;
|
|
|
|
tm *ptm;
|
|
|
|
time_t t;
|
|
|
|
Vector vPlayer = vec_zero;
|
|
|
|
char szFile[64];
|
|
|
|
int i2;
|
|
|
|
//int i1;
|
|
|
|
int i;
|
|
|
|
char szTemp[65536];
|
|
|
|
char szTemp2[1024];
|
|
|
|
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
va_start(va, pszFmt);
|
|
|
|
|
|
|
|
sv_mapname = gi.Cvar_Get("mapname", "unknown", 0);
|
|
|
|
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
vPlayer = p->origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = sprintf(
|
|
|
|
szTemp,
|
|
|
|
"map = %s\n"
|
|
|
|
"time = %i (%i:%02i)\n"
|
|
|
|
"entnum = %i, targetname = '%s'\n"
|
|
|
|
"origin = (%g %g %g)\n"
|
|
|
|
"think = %s, thinkstate = %s\n"
|
|
|
|
"type_idle = %s\n"
|
|
|
|
"type_attack = %s\n"
|
|
|
|
"m_State = %i, m_pszDebugState = %s\n"
|
|
|
|
"player is at (%g %g %g)\n"
|
|
|
|
"--------------------------------------\n",
|
|
|
|
sv_mapname->string,
|
|
|
|
level.inttime,
|
|
|
|
level.inttime / 60000,
|
|
|
|
level.inttime / 1000 - 60 * (level.inttime / 60000),
|
|
|
|
entnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
origin[0],
|
|
|
|
origin[1],
|
|
|
|
origin[2],
|
|
|
|
ThinkName().c_str(),
|
|
|
|
ThinkStateName().c_str(),
|
|
|
|
Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_IDLE]]).c_str(),
|
|
|
|
Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]).c_str(),
|
|
|
|
m_State,
|
|
|
|
m_pszDebugState,
|
|
|
|
vPlayer[0],
|
|
|
|
vPlayer[1],
|
|
|
|
vPlayer[2]);
|
|
|
|
|
|
|
|
if (pszFmt)
|
|
|
|
{
|
|
|
|
i2 = i + vsprintf(&szTemp[i], pszFmt, va);
|
|
|
|
}
|
|
|
|
if (i2 != i)
|
|
|
|
{
|
|
|
|
strcpy(&szTemp[i2], "\n--------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
t = time(0);
|
|
|
|
ptm = localtime(&t);
|
|
|
|
sprintf(
|
|
|
|
szFile,
|
|
|
|
"main\\ai_trace_%s_%i_%i_%02i%02i.log",
|
|
|
|
sv_mapname->string,
|
|
|
|
ptm->tm_mon + 1,
|
|
|
|
ptm->tm_mday,
|
|
|
|
ptm->tm_hour,
|
|
|
|
ptm->tm_min);
|
|
|
|
|
|
|
|
for (i=0; szFile[i]; i++)
|
|
|
|
{
|
|
|
|
if (szFile[i] == '\\' || szFile[i] == '/')
|
|
|
|
szFile[i] = '_';
|
|
|
|
}
|
|
|
|
sprintf(szTemp2, "Include '%s' in your bug report!", szFile);
|
|
|
|
//PreAssertMessage:
|
|
|
|
fprintf(stderr, "IMPORTANT: %s\n", szTemp2);
|
|
|
|
|
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return ::va(
|
|
|
|
"\n"
|
|
|
|
"\t-------------------------- IMPORTANT REMINDER --------------------------\n"
|
|
|
|
"\n"
|
|
|
|
"\tinclude '%s' in your bug report! \n"
|
|
|
|
"\n"
|
|
|
|
"\t----------------------- END IMPORTANT REMINDER -----------------------\n"
|
|
|
|
"\n"
|
|
|
|
"%s",
|
|
|
|
szFile,
|
|
|
|
szTemp);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetMoveDoneRadius
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float moveDoneR = ev->GetFloat(1);
|
|
|
|
m_fMoveDoneRadiusSquared = Square(moveDoneR);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::StoppedWaitFor
|
|
|
|
|
|
|
|
Called when stopped wait for an actor.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::StoppedWaitFor
|
|
|
|
(
|
|
|
|
const_str name,
|
|
|
|
bool bDeleting
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
g_iInThinks++;
|
|
|
|
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (func->FinishedAnimation)
|
|
|
|
{
|
|
|
|
(this->*func->FinishedAnimation)();
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
g_iInThinks--;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventHasCompleteLookahead
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int completeLH = PathExists() && PathHasCompleteLookahead();
|
|
|
|
|
|
|
|
ev->AddInteger(completeLH);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventPathDist
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
float dist = 0;
|
|
|
|
if (PathExists() && !PathComplete())
|
|
|
|
{
|
|
|
|
dist = PathDist();
|
|
|
|
}
|
|
|
|
ev->AddFloat(dist);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventCanShootEnemyFrom
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int canShoot = false;
|
|
|
|
if (m_Enemy)
|
|
|
|
{
|
|
|
|
canShoot = CanSeeFrom(ev->GetVector(1), m_Enemy);
|
|
|
|
}
|
|
|
|
ev->AddInteger(canShoot);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetInReload
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
m_bInReload = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetInReload
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(m_bInReload);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetReloadCover
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNeedReload = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventBreakSpecial
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
mbBreakSpecialAttack = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventCanShoot
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Entity *target = ev->GetEntity(1);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (!target)
|
|
|
|
{
|
|
|
|
ScriptError("canshoot applied to null listener");
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(CanShoot(target));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetBalconyHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fBalconyHeight = ev->GetFloat(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetBalconyHeight
|
2023-10-11 22:49:06 +02:00
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddFloat(m_fBalconyHeight);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::BecomeTurretGuy
|
2016-03-27 11:49:47 +02:00
|
|
|
(
|
2023-10-11 22:49:06 +02:00
|
|
|
void
|
2016-03-27 11:49:47 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_IDLE);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
|
|
|
|
SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE);
|
|
|
|
SetThink(THINKSTATE_GRENADE, THINK_GRENADE);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (CurrentThink() == THINK_IDLE && Turret_DecideToSelectState())
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
TransitionState(100, 0);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::AimAtEnemyBehavior
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Aiming at enemy behaviour.
|
|
|
|
Usally called after SetEnemyPos()
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::AimAtEnemyBehavior
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
AimAtTargetPos();
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Aim();
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::ForwardLook
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::ForwardLook
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//fixme: this is an inline function.
|
|
|
|
m_bHasDesiredLookAngles = false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::SetDesiredLookDir
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change desired look direction.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::SetDesiredLookDir
|
|
|
|
(
|
|
|
|
vec3_t dir
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookAngles = true;
|
|
|
|
vectoangles( dir, m_DesiredLookAngles );
|
|
|
|
m_DesiredLookAngles[ 1 ] = m_DesiredLookAngles[ 1 ] - angles[ 1 ];
|
|
|
|
m_DesiredLookAngles[ 1 ] = AngleNormalize180( m_DesiredLookAngles[ 1 ] );
|
|
|
|
m_DesiredLookAngles[ 0 ] = AngleNormalize180( m_DesiredLookAngles[ 0 ] );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::SetDesiredLookAnglesRelative
|
|
|
|
|
|
|
|
Change desired look angles relatively.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::SetDesiredLookAnglesRelative
|
|
|
|
(
|
|
|
|
vec3_t ang
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookAngles = true;
|
|
|
|
m_DesiredLookAngles[ 0 ] = AngleNormalize180( ang[ 0 ] );
|
|
|
|
m_DesiredLookAngles[ 1 ] = AngleNormalize180( ang[ 1 ] );
|
|
|
|
m_DesiredLookAngles[ 2 ] = AngleNormalize180( ang[ 2 ] );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::AimAtTargetPos
|
|
|
|
|
|
|
|
Aim at mTargetPos.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::AimAtTargetPos
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vDir = mTargetPos - EyePosition() + Vector(0, 0, 16);
|
|
|
|
SetDesiredLookDir(vDir);
|
|
|
|
m_DesiredGunDir[0] = 360.0f - vDir.toPitch();
|
|
|
|
m_DesiredGunDir[1] = vDir.toYaw();
|
|
|
|
m_DesiredGunDir[2] = 0;
|
|
|
|
|
|
|
|
SetDesiredYawDir(vDir);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::AimAtAimNode
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Aim at m_aimNode.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::AimAtAimNode
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
mTargetPos = m_aimNode->origin;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
AimAtTargetPos();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::NextUpdateTime
|
|
|
|
|
|
|
|
Returns next update time.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
int Actor::NextUpdateTime
|
|
|
|
(
|
|
|
|
int iLastUpdateTime,
|
|
|
|
int iUpdatePeriod
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
int i = iLastUpdateTime;
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
do
|
|
|
|
i += iUpdatePeriod;
|
|
|
|
while( i < level.inttime );
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return i;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
void Actor::UpdateBoneControllers()
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector torsoAngles, headAngles, LocalLookAngles, vec1, vLookDest, vec2, vLookDir, lineVec, eyePosition;
|
|
|
|
float error, pitchError, torsoYawError, fAlpha; //, min_accel_change, max_accel_change, max_change, yawError, tolerable_error
|
|
|
|
|
|
|
|
if (m_bHasDesiredLookAngles)
|
|
|
|
{
|
|
|
|
if (g_showlookat->integer == entnum || g_showlookat->integer == -1)
|
|
|
|
{
|
|
|
|
float myAxis[3][3], lookAxis[3][3];
|
|
|
|
orientation_t tag_or;
|
|
|
|
GetRawTag("eyes bone", &tag_or);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
AnglesToAxis(angles, myAxis);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vec1 = origin;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
//sizeof(orientation_t);
|
|
|
|
VectorMA(vec1, tag_or.origin[i], myAxis[i], vec1);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
if (m_bHasDesiredLookDest)
|
|
|
|
{
|
|
|
|
vLookDest = m_vDesiredLookDest;
|
|
|
|
}
|
|
|
|
else if (m_pLookEntity)
|
|
|
|
{
|
|
|
|
if (m_pLookEntity->IsSubclassOfSentient())
|
|
|
|
{
|
|
|
|
vLookDest = ((Sentient *)m_pLookEntity.Pointer())->EyePosition();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vLookDest = m_pLookEntity->centroid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vLookDest = vec_zero;
|
|
|
|
}
|
|
|
|
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
AnglesToAxis(angles + m_DesiredLookAngles, lookAxis);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2 = vLookDest - vec1;
|
|
|
|
|
|
|
|
VectorNormalize(vec2);
|
|
|
|
|
|
|
|
float fDist = (vec2 - lookAxis[0]).length();
|
|
|
|
if (fDist >= 0.1)
|
|
|
|
{
|
|
|
|
lineVec = Vector(128, 0, 0);
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
VectorMA(vec1, lineVec[i], lookAxis[i], vLookDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vLookDir = vLookDest;
|
|
|
|
|
|
|
|
if (fDist >= 0.04)
|
|
|
|
{
|
|
|
|
fAlpha = ((0.1 - fDist) / 0.06);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAlpha = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(8, 8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, -8, 8), vLookDest + Vector(8, -8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(-8, 8, 8), vLookDest + Vector(-8, 8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(8, -8, 8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(-8, 8, -8), vLookDest + Vector(-8, -8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, 8, 8), vLookDest + Vector(-8, 8, 8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, 8, -8), vLookDest + Vector(-8, 8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, -8, 8), vLookDest + Vector(-8, -8, 8), 0, 0, fAlpha, fAlpha);
|
|
|
|
G_DebugLine(vLookDest + Vector(8, -8, -8), vLookDest + Vector(-8, -8, -8), 0, 0, fAlpha, fAlpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DebugLine(vec1, vLookDir, 0, 0, 1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
//sizeof(orientation_t);
|
|
|
|
VectorMA(vLookDir, Vector(0, 0, -2)[i], lookAxis[i], vLookDir);
|
|
|
|
VectorMA(vec1, Vector(0, 0, -2)[i], lookAxis[i], vec1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DebugLine(vec1, vLookDir, 0, 0, 1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
//sizeof(orientation_t);
|
|
|
|
VectorMA(vLookDir, Vector(0, 2, 0)[i], lookAxis[i], vLookDir);
|
|
|
|
VectorMA(vec1, Vector(0, 2, 0)[i], lookAxis[i], vec1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DebugLine(vec1, vLookDir, 0, 0, 1, 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LocalLookAngles = m_DesiredLookAngles;
|
|
|
|
|
|
|
|
eyePosition = vec_zero;
|
|
|
|
VectorClear(edict->s.eyeVector);
|
|
|
|
LocalLookAngles.AngleVectorsLeft(&eyePosition, NULL, NULL);
|
|
|
|
VectorCopy(eyePosition, edict->s.eyeVector);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VectorClear(edict->s.eyeVector);
|
|
|
|
|
|
|
|
LocalLookAngles = vec_zero;
|
|
|
|
}
|
|
|
|
headAngles = GetControllerAngles(HEAD_TAG);
|
|
|
|
torsoAngles = GetControllerAngles(TORSO_TAG);
|
|
|
|
|
|
|
|
|
|
|
|
torsoYawError = LocalLookAngles[1] - torsoAngles[1];
|
|
|
|
error = torsoYawError - headAngles[1];
|
|
|
|
|
|
|
|
pitchError = LocalLookAngles[0] - headAngles[0];
|
|
|
|
|
|
|
|
if (torsoYawError <= 180)
|
|
|
|
{
|
|
|
|
if (torsoYawError < -180.0)
|
|
|
|
torsoYawError += 360;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
torsoYawError -= 360;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (torsoYawError >= 0.0)
|
|
|
|
{
|
|
|
|
if (error < -120.0)
|
|
|
|
error += 360.0;
|
|
|
|
}
|
|
|
|
else if (error > 120.0)
|
|
|
|
{
|
|
|
|
error -= 360.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float fErr1, fErr2, fAng1, fAng2, fAng3, fFrameTorsoDist, fAng4, fAng5, fAng6, fAng7;
|
|
|
|
float fAng8, fAng9, fAng10;
|
|
|
|
if (m_iLookFlags)
|
|
|
|
{
|
|
|
|
fAng6 = error;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (error <= 25.0)
|
|
|
|
{
|
|
|
|
if (error >= -25.0)
|
|
|
|
{
|
|
|
|
fErr1 = 0.0;
|
|
|
|
//goto LABEL_15;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fErr1 = (error + 25.0) * 0.2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fErr1 = (error - 25.0) * 0.2;
|
|
|
|
}
|
|
|
|
|
|
|
|
fErr2 = error + headAngles[1];
|
|
|
|
|
|
|
|
fAng1 = -torsoAngles[1];
|
|
|
|
|
|
|
|
if (fErr2 > fAng1)
|
|
|
|
{
|
|
|
|
fErr2 = -torsoAngles[1];
|
|
|
|
fAng1 = error + headAngles[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fErr2 <= error)
|
|
|
|
{
|
|
|
|
fAng2 = fAng1;
|
|
|
|
if (error <= fAng1)
|
|
|
|
fAng2 = error;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng2 = fErr2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fAng3 = m_fTorsoCurrentTurnSpeed + level.frametime * 15.0;
|
|
|
|
|
|
|
|
if (fAng2 <= fAng3)
|
|
|
|
{
|
|
|
|
fAng3 = fAng2;
|
|
|
|
if (fAng2 < m_fTorsoCurrentTurnSpeed - level.frametime * 15.0)
|
|
|
|
fAng3 = m_fTorsoCurrentTurnSpeed + level.frametime * 15.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fFrameTorsoDist = level.frametime * m_fTorsoMaxTurnSpeed;
|
|
|
|
|
|
|
|
if (-fFrameTorsoDist <= fAng3)
|
|
|
|
{
|
|
|
|
fAng4 = fFrameTorsoDist;
|
|
|
|
if (fAng3 <= fFrameTorsoDist)
|
|
|
|
fAng4 = fAng3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng4 = -fFrameTorsoDist;
|
|
|
|
}
|
|
|
|
|
|
|
|
torsoAngles[1] += fAng4;
|
|
|
|
if (torsoAngles[1] <= 30.0)
|
|
|
|
{
|
|
|
|
if (torsoAngles[1] >= -30.0)
|
|
|
|
{
|
|
|
|
fAng5 = fAng4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
torsoAngles[1] = -30.0;
|
|
|
|
fAng5 = fAng4 - (torsoAngles[1] + 30.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
torsoAngles[1] = 30.0;
|
|
|
|
fAng5 = fAng4 - (torsoAngles[1] - 30.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fTorsoCurrentTurnSpeed = fAng5;
|
|
|
|
|
|
|
|
//only yaw (left/right) angles are allowed.
|
|
|
|
torsoAngles[0] = 0.0;
|
|
|
|
torsoAngles[2] = 0.0;
|
|
|
|
SetControllerAngles(TORSO_TAG, torsoAngles);
|
|
|
|
//gi.Printf("Torso angles: %f %f %f\n", torsoAngles.x, torsoAngles.y, torsoAngles.z);
|
|
|
|
|
|
|
|
fAng6 = error - fAng5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fAng6 > 15.0)
|
|
|
|
{
|
|
|
|
fAng7 = (fAng6 - 15.0) * 4.0 * level.frametime;
|
|
|
|
}
|
|
|
|
else if (-15.0 > fAng6)
|
|
|
|
{
|
|
|
|
fAng7 = (fAng6 + 15.0) * 4.0 * level.frametime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng7 = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fAng8 = fAng6;
|
|
|
|
fAng9 = -headAngles[1];
|
|
|
|
|
|
|
|
if (fAng8 > fAng9)
|
|
|
|
{
|
|
|
|
fAng8 = -headAngles[1];
|
|
|
|
fAng9 = fAng6;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fAng8 > fAng7)
|
|
|
|
{
|
|
|
|
fAng7 = fAng8;
|
|
|
|
}
|
|
|
|
else if (fAng7 > fAng9)
|
|
|
|
{
|
|
|
|
fAng7 = fAng9;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (-(level.frametime * m_fHeadMaxTurnSpeed) <= fAng7)
|
|
|
|
{
|
|
|
|
fAng10 = (level.frametime * m_fHeadMaxTurnSpeed);
|
|
|
|
if (fAng7 <= fAng10)
|
|
|
|
fAng10 = fAng7;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng10 = -(level.frametime * m_fHeadMaxTurnSpeed);
|
|
|
|
}
|
|
|
|
|
|
|
|
headAngles[1] += fAng10;
|
|
|
|
if (headAngles[1] > 60)
|
|
|
|
{
|
|
|
|
headAngles[1] = 60;
|
|
|
|
}
|
|
|
|
else if (headAngles[1] < -60)
|
|
|
|
{
|
|
|
|
headAngles[1] = -60;
|
|
|
|
}
|
|
|
|
|
|
|
|
float fAng11, fAng12, fAng13;
|
|
|
|
|
|
|
|
fAng11 = fabs(LocalLookAngles[0]);
|
|
|
|
|
|
|
|
if (fAng11 > 15)
|
|
|
|
{
|
|
|
|
fAng11 = 15;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pitchError > fAng11)
|
|
|
|
{
|
|
|
|
fAng12 = 0.2 * (pitchError - fAng11);
|
|
|
|
}
|
|
|
|
else if (-fAng11 > pitchError)
|
|
|
|
{
|
|
|
|
fAng12 = 0.2 * (pitchError + fAng11);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng12 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (-(level.frametime * m_fHeadMaxTurnSpeed) <= fAng12)
|
|
|
|
{
|
|
|
|
fAng13 = (level.frametime * m_fHeadMaxTurnSpeed);
|
|
|
|
if (fAng12 <= fAng13)
|
|
|
|
fAng13 = fAng12;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng13 = -(level.frametime * m_fHeadMaxTurnSpeed);
|
|
|
|
}
|
|
|
|
|
|
|
|
headAngles[0] += fAng13;
|
|
|
|
|
|
|
|
if (headAngles[0] > 35.0)
|
|
|
|
headAngles[0] = 35.0;
|
|
|
|
else if (headAngles[0] < -35.0)
|
|
|
|
headAngles[0] = -35.0;
|
|
|
|
|
|
|
|
headAngles[2] = 0.0;
|
|
|
|
|
|
|
|
if (m_iLookFlags)
|
|
|
|
{
|
|
|
|
headAngles[0] *= 0.5;
|
|
|
|
headAngles[1] *= 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetControllerAngles(HEAD_TAG, headAngles);
|
|
|
|
//gi.Printf("Head angles: %f %f %f\n", headAngles.x, headAngles.y, headAngles.z);
|
|
|
|
|
|
|
|
|
|
|
|
Vector armAngles = GetControllerAngles(ARMS_TAG);
|
|
|
|
|
|
|
|
float fAng14 = m_vLUpperArmDesiredAngles[1] - armAngles[1];
|
|
|
|
|
|
|
|
if (fAng14 <= 180.0)
|
|
|
|
{
|
|
|
|
if (fAng14 < -180.0)
|
|
|
|
fAng14 += 360.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng14 -= 360.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float fAng15;
|
|
|
|
|
|
|
|
if (-(level.frametime * m_fLUpperArmTurnSpeed) <= fAng14)
|
|
|
|
{
|
|
|
|
fAng15 = (level.frametime * m_fLUpperArmTurnSpeed);
|
|
|
|
if (fAng14 <= fAng15)
|
|
|
|
fAng15 = fAng14;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fAng15 = -(level.frametime * m_fLUpperArmTurnSpeed);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector newArmAngles(m_vLUpperArmDesiredAngles[0], fAng15 + armAngles[1], 0);
|
|
|
|
SetControllerAngles(ARMS_TAG, newArmAngles);
|
|
|
|
//gi.Printf("Arm angles: %f %f %f\n", newArmAngles.x, newArmAngles.y, newArmAngles.z);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
return;
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
*/
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::CurrentThink
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Current think.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
int Actor::CurrentThink
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
return m_Think[ m_ThinkLevel ];
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::IsAttacking
|
|
|
|
|
|
|
|
Returns true if actor is in attack state.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::IsAttacking
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return m_ThinkStates[ THINKLEVEL_NORMAL ] == THINKSTATE_ATTACK;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetDestIdle
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
// not found in ida
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetDestIdle2
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
// not found in ida
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventGetBreathSteam
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ev->AddInteger(m_bBreathSteam);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetBreathSteam
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_bBreathSteam = ev->GetInteger(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
void Actor::EventSetNextBreathTime
|
|
|
|
(
|
|
|
|
Event *ev
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptVariable sVar;
|
|
|
|
ScriptThread *t = Director.CreateThread("global/breathe.scr", "nextbreathtime");
|
|
|
|
|
|
|
|
sVar.setFloatValue(ev->GetFloat(1));
|
|
|
|
t->Execute(&sVar, 1);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::AvoidingFacingWall
|
|
|
|
(
|
|
|
|
void
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
return m_eDontFaceWallMode <= 8;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
bool Actor::EnemyIsDisguised
|
|
|
|
(
|
|
|
|
void
|
|
|
|
)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
return ( m_bEnemyIsDisguised || (m_Enemy && m_Enemy->m_bIsDisguised) ) && ( !m_bForceAttackPlayer && m_ThinkState != THINKSTATE_ATTACK );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|