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
|
|
|
|
2023-10-12 18:19:22 +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
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
const char *gAmericanVoices[] = {"a", "c", "h"};
|
|
|
|
const char *gGermanVoices[] = {"a", "c", "d"};
|
2018-08-19 08:26:59 +02:00
|
|
|
|
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
|
|
|
|
);
|
2023-10-12 18:19:22 +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
|
|
|
|
);
|
2023-10-12 18:19:22 +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
|
|
|
|
);
|
2023-10-12 18:19:22 +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
|
|
|
(
|
2023-10-12 18:19:22 +02:00
|
|
|
"mumble",
|
|
|
|
EV_DEFAULT,
|
2023-10-11 22:49:06 +02:00
|
|
|
"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
|
|
|
|
);
|
2023-10-12 18:19:22 +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
|
|
|
|
);
|
2023-10-12 18:19:22 +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
|
|
|
|
);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
CLASS_DECLARATION(SimpleActor, Actor, "Actor") {
|
2023-10-12 19:21:41 +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_Anim_Attached, &Actor::PlayAttachedAnimation },
|
|
|
|
{&EV_Actor_AnimScript, &Actor::EventAnimScript },
|
|
|
|
{&EV_Actor_AnimScript_Scripted, &Actor::EventAnimScript_Scripted },
|
|
|
|
{&EV_Actor_AnimScript_Noclip, &Actor::EventAnimScript_Noclip },
|
|
|
|
{&EV_Actor_AnimScript_Attached, &Actor::EventAnimScript_Attached },
|
|
|
|
{&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_SetPreAlarmThread, &Actor::EventSetPreAlarmThread },
|
|
|
|
{&EV_Actor_SetPreAlarmThread2, &Actor::EventSetPreAlarmThread },
|
|
|
|
{&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_GetVisibilityThreshold, &Actor::EventGetVisibilityThreshold },
|
|
|
|
{&EV_Actor_SetVisibilityThreshold, &Actor::EventSetVisibilityThreshold },
|
|
|
|
{&EV_Actor_SetVisibilityThreshold2, &Actor::EventSetVisibilityThreshold },
|
|
|
|
{&EV_Actor_SetDefaultVisibilityThreshold, &Actor::EventSetDefaultVisibilityThreshold },
|
|
|
|
{&EV_Actor_GetSuppressChance, &Actor::EventGetSuppressChance },
|
|
|
|
{&EV_Actor_SetSuppressChance, &Actor::EventSetSuppressChance },
|
|
|
|
{&EV_Actor_SetSuppressChance2, &Actor::EventSetSuppressChance },
|
|
|
|
{&EV_Actor_GetPainHandler, &Actor::EventGetPainHandler },
|
|
|
|
{&EV_Actor_SetPainHandler, &Actor::EventSetPainHandler },
|
|
|
|
{&EV_Actor_GetDeathHandler, &Actor::EventGetDeathHandler },
|
|
|
|
{&EV_Actor_SetDeathHandler, &Actor::EventSetDeathHandler },
|
|
|
|
{&EV_Actor_GetAttackHandler, &Actor::EventGetAttackHandler },
|
|
|
|
{&EV_Actor_SetAttackHandler, &Actor::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 },
|
|
|
|
// FIXME: removed since 2.0?
|
|
|
|
//{&EV_Actor_GetBreathSteam, &Actor::EventGetBreathSteam },
|
|
|
|
//{&EV_Actor_SetBreathSteam, &Actor::EventSetBreathSteam },
|
|
|
|
//{&EV_Actor_SetBreathSteam2, &Actor::EventSetBreathSteam },
|
|
|
|
{&EV_Actor_CalcGrenadeToss, &Actor::EventCalcGrenadeToss },
|
|
|
|
{&EV_Actor_CalcGrenadeToss2, &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_GetMoveDoneRadius, &Actor::EventGetMoveDoneRadius },
|
|
|
|
{&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_Actor_SetIgnoreBadPlace, &Actor::EventSetIgnoreBadPlace },
|
|
|
|
{&EV_Actor_SetIgnoreBadPlace2, &Actor::EventSetIgnoreBadPlace },
|
|
|
|
{&EV_Actor_GetIgnoreBadPlace, &Actor::EventGetIgnoreBadPlace },
|
|
|
|
{&EV_Actor_FindEnemy, &Actor::EventFindEnemy },
|
|
|
|
{&EV_Actor_EnableEnemySwitch, &Actor::EventEnableEnemySwitch },
|
|
|
|
{&EV_Actor_DisableEnemySwitch, &Actor::EventDisableEnemySwitch },
|
|
|
|
{&EV_Actor_SetRunAnimRate, &Actor::EventSetRunAnimRate },
|
|
|
|
{&EV_Actor_SetRunAnimRate2, &Actor::EventSetRunAnimRate },
|
|
|
|
{&EV_Actor_GetRunAnimRate, &Actor::EventGetRunAnimRate },
|
|
|
|
{&EV_Stop, &Actor::Landed },
|
|
|
|
{&EV_Actor_SetNationality, &Actor::SetNationality },
|
|
|
|
{&EV_Actor_SetNationality2, &Actor::SetNationality },
|
|
|
|
{&EV_Actor_GetNationality, &Actor::GetNationality },
|
|
|
|
{&EV_Actor_WriteStats, &Actor::EventWriteStats },
|
|
|
|
{&EV_Actor_CuriousOff, &Actor::EventCuriousOff },
|
|
|
|
{&EV_Actor_CuriousOn, &Actor::EventCuriousOn },
|
|
|
|
{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];
|
2023-10-12 18:19:22 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
STRING_DEAD};
|
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
STRING_NOCLIP};
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (LoadingSavegame) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
edict->s.eType = ET_MODELANIM;
|
|
|
|
edict->r.svFlags |= SVF_MONSTER;
|
|
|
|
edict->r.ownerNum = ENTITYNUM_NONE;
|
2023-10-12 18:19:22 +02:00
|
|
|
edict->clipmask = MASK_MONSTERSOLID;
|
|
|
|
setMoveType(MOVETYPE_WALK);
|
2023-10-11 22:49:06 +02:00
|
|
|
mass = 175;
|
|
|
|
flags |= FL_THINK;
|
|
|
|
flags &= ~FL_ANIMATE;
|
|
|
|
setContentsSolid();
|
2023-10-12 18:19:22 +02:00
|
|
|
setSolidType(SOLID_BBOX);
|
|
|
|
m_fFov = 90.0f;
|
|
|
|
takedamage = DAMAGE_AIM;
|
|
|
|
m_fFovDot = cos(0.5 * m_fFov * M_PI / 180);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eAnimMode = 0;
|
|
|
|
Anim_Emotion(EMOTION_NONE);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bDoPhysics = true;
|
|
|
|
path_failed_time = 0;
|
|
|
|
health = 100;
|
|
|
|
max_health = 100;
|
|
|
|
m_fAngleYawSpeed = 360;
|
|
|
|
m_fHeadMaxTurnSpeed = 520;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHeadAnglesAchieved = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
VectorClear(m_vHeadDesiredAngles);
|
|
|
|
m_fLUpperArmTurnSpeed = 360;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bLUpperArmAnglesAchieved = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
VectorClear(m_vLUpperArmDesiredAngles);
|
|
|
|
m_fTorsoMaxTurnSpeed = 120;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fTorsoCurrentTurnSpeed = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bTorsoAnglesAchieved = true;
|
|
|
|
VectorClear(m_vTorsoDesiredAngles);
|
|
|
|
m_pLookEntity = NULL;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pPointEntity = NULL;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pTurnEntity = NULL;
|
|
|
|
VectorClear(edict->s.eyeVector);
|
|
|
|
m_bDoAI = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bTurretNoInitialCover = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
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);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bLockThinkState = false;
|
|
|
|
InitThinkStates();
|
|
|
|
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fMinDistance = 128;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistanceSquared = Square(128);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fMaxDistance = 1024;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDistanceSquared = Square(1024);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fLeash = 512;
|
|
|
|
m_fLeashSquared = Square(512);
|
|
|
|
m_iEyeUpdateTime = level.inttime;
|
|
|
|
if (m_iEyeUpdateTime < 1000) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEyeUpdateTime = 1000;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEyeUpdateTime += rand() % 100 + 100;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyVisibleChangeTime = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iLastEnemyPosChangeTime = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_vScriptGoal = vec_origin;
|
|
|
|
m_iNextWatchStepTime = 0;
|
|
|
|
m_iCuriousTime = 0;
|
|
|
|
m_iCuriousLevel = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(0);
|
|
|
|
m_bScriptGoalValid = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDisguiseDistSquared = 256 * 256;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMoveDoneRadiusSquared = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iCurrentHistory = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bDog = false;
|
|
|
|
m_bBecomeRunner = false;
|
|
|
|
mVoiceType = -1;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::setContentsSolid(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
setContents(CONTENTS_NOBOTCLIP);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EndStates(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i < NUM_THINKLEVELS; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]];
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (func->EndState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->EndState)();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pAnimThread) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pAnimThread->AbortRegistration(STRING_EMPTY, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::ClearStates(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i < NUM_THINKSTATES; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink((eThinkState)i, THINK_VOID);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::ResolveVoiceType(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
char validVoice[128];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mVoiceType == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
int d = 3.0 * 0.99 * random();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Team == TEAM_AMERICAN) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mVoiceType = gAmericanVoices[d][0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mVoiceType = gGermanVoices[d][0];
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (m_Team == TEAM_AMERICAN) {
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
if (gAmericanVoices[i][0] == mVoiceType) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
validVoice[0] = '\0';
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i < 3; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
strcat(validVoice, gAmericanVoices[i]);
|
|
|
|
strcat(validVoice, " ");
|
|
|
|
}
|
|
|
|
Com_Printf("ERROR: Bad voice type %c. Valid American voicetypes are: %s\n", mVoiceType, validVoice);
|
|
|
|
mVoiceType = -1;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
int d = 3.0 * 0.99 * random();
|
2023-10-11 22:49:06 +02:00
|
|
|
mVoiceType = gAmericanVoices[d][0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
if (gGermanVoices[i][0] == mVoiceType) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
validVoice[0] = '\0';
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i < 3; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
strcat(validVoice, gGermanVoices[i]);
|
|
|
|
strcat(validVoice, " ");
|
|
|
|
}
|
|
|
|
Com_Printf("ERROR: Bad voice type %c. Valid German voicetypes are: %s\n", mVoiceType, validVoice);
|
|
|
|
mVoiceType = -1;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
int d = 3.0 * 0.99 * random();
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventStart(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ResolveVoiceType();
|
2023-10-12 18:19:22 +02:00
|
|
|
setSize(MINS, MAXS); //notsure
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
droptofloor(16384);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (level.Spawned()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unregister(STRING_SPAWN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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();
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +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;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
mm->groundPlane = m_groundPlane;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::GetMoveInfo(mmove_t *mm)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macros
|
2023-10-12 18:19:22 +02:00
|
|
|
m_walking = mm->walking;
|
|
|
|
m_groundPlane = mm->groundPlane;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_groundPlaneNormal = mm->groundPlaneNormal;
|
2023-10-12 18:19:22 +02:00
|
|
|
groundentity = NULL;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
TouchStuff(mm);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_eAnimMode >= 2) {
|
|
|
|
if (m_eAnimMode <= 3) {
|
|
|
|
if (mm->hit_temp_obstacle) {
|
|
|
|
if (mm->hit_temp_obstacle & 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.Clear();
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!IsTeamMate(p)) {
|
|
|
|
if (!m_bEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDesiredEnableEnemy = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bEnableEnemy = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
SetLeashHome(origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
BecomeTurretGuy();
|
|
|
|
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, p);
|
|
|
|
m_bForceAttackPlayer = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
velocity = vec_zero;
|
|
|
|
return;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm->hit_obstacle) {
|
|
|
|
if (level.inttime >= m_Path.Time() + 1000) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.ReFindPath(origin, this);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (!m_Path.NextNode()
|
|
|
|
|| (!(m_Path.NextNode()->bAccurate && m_Path.IsSide())
|
2023-10-11 22:49:06 +02:00
|
|
|
&& m_Path.NextNode() == m_Path.CurrentNode()
|
2023-10-12 18:19:22 +02:00
|
|
|
&& m_Path.CurrentNode() != m_Path.StartNode())) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.Clear();
|
|
|
|
velocity = vec_zero;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Path.CurrentNode() == m_Path.StartNode()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ BAD FAILSAFE: %.2f %.2f %.2f, '%s'\n",
|
|
|
|
origin[0],
|
|
|
|
origin[1],
|
|
|
|
origin[2],
|
2023-10-12 18:19:22 +02:00
|
|
|
targetname.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DoFailSafeMove(m_Path.NextNode()->point);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (velocity.lengthXYSquared() < -0.69999999 && level.inttime >= m_Path.Time() + 1000) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.ReFindPath(origin, this);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_eAnimMode == 4) {
|
|
|
|
if (mm->hit_temp_obstacle) {
|
|
|
|
if (mm->hit_temp_obstacle & 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.Clear();
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!IsTeamMate(p)) {
|
|
|
|
if (!m_bEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDesiredEnableEnemy = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bEnableEnemy = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
SetLeashHome(origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
BecomeTurretGuy();
|
|
|
|
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, p);
|
|
|
|
m_bForceAttackPlayer = true;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (mm->hit_obstacle) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
"Actor::GetMoveInfo"
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
DoFailSafeMove(trace.endpos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setOrigin(mm->origin);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (VectorLengthSquared(mm->velocity) < 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
velocity = vec_zero;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::TouchStuff(mmove_t *mm)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
int i, j;
|
|
|
|
gentity_t *other;
|
|
|
|
Event *event;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (getMoveType() != MOVETYPE_NOCLIP) {
|
|
|
|
G_TouchTriggers(this);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (i = 0; i < mm->numtouch; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
other = &g_entities[mm->touchents[i]];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (j = 0; j < i; j++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
gentity_t *ge = &g_entities[j];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ge == other) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (j != i) {
|
2023-10-11 22:49:06 +02:00
|
|
|
// duplicated
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't bother touching the world
|
2023-10-12 18:19:22 +02:00
|
|
|
if ((!other->entity) || (other->entity == world)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ResetBoneControllers(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (edict->s.bone_tag[HEAD_TAG] != -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetControllerAngles(HEAD_TAG, vec_zero);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (edict->s.bone_tag[TORSO_TAG] != -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetControllerAngles(TORSO_TAG, vec_zero);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (edict->s.bone_tag[ARMS_TAG] != -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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]
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
torsoAngles[2] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
headAngles[0] = 0.0;
|
|
|
|
headAngles[1] = 0.0;
|
|
|
|
headAngles[2] = 0.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
torsoAngles[0] = 0.0;
|
|
|
|
torsoAngles[1] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bHasDesiredLookAngles) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v1 = g_showlookat->integer;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v1 != entnum && v1 != -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ACTOR_UPDATEBONECONTROLLERS_4:
|
2023-10-12 18:19:22 +02:00
|
|
|
v2 = m_DesiredLookAngles[0];
|
2023-10-11 22:49:06 +02:00
|
|
|
LocalLookAngles[0] = m_DesiredLookAngles[0];
|
|
|
|
LocalLookAngles[1] = m_DesiredLookAngles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v3 = m_DesiredLookAngles[2];
|
|
|
|
v178[0] = 0.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
LocalLookAngles[2] = v3;
|
2023-10-12 18:19:22 +02:00
|
|
|
v177[2] = v3;
|
|
|
|
v178[1] = 0.0;
|
|
|
|
v178[2] = 0.0;
|
|
|
|
v177[0] = v2;
|
|
|
|
v177[1] = LocalLookAngles[1];
|
2023-10-11 22:49:06 +02:00
|
|
|
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");
|
2023-10-12 18:19:22 +02:00
|
|
|
v77 = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
tag_or = G_TIKI_Orientation(edict, tagnum & 0x3FF);
|
|
|
|
AnglesToAxis(angles, myAxis);
|
|
|
|
v197[0] = origin[0];
|
|
|
|
v197[1] = origin[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v78 = v197[0];
|
|
|
|
v79 = v197[1];
|
|
|
|
v80 = origin[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
v197[2] = origin[2];
|
2023-10-12 18:19:22 +02:00
|
|
|
v81 = &v202;
|
|
|
|
while (1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v77 > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
v90 = v88;
|
|
|
|
v80 = v89;
|
|
|
|
v79 = v90;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v197[2] = v89;
|
|
|
|
v197[1] = v88;
|
|
|
|
v197[0] = v78;
|
2023-10-11 22:49:06 +02:00
|
|
|
vLookDest[0] = 0.0;
|
|
|
|
vLookDest[1] = 0.0;
|
|
|
|
vLookDest[2] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bHasDesiredLookDest) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v188 = m_vDesiredLookDest[0];
|
|
|
|
v189 = m_vDesiredLookDest[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v91 = m_vDesiredLookDest[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
ACTOR_UPDATEBONECONTROLLERS_105:
|
2023-10-12 18:19:22 +02:00
|
|
|
v190 = v91;
|
2023-10-11 22:49:06 +02:00
|
|
|
vLookDest[0] = v188;
|
|
|
|
vLookDest[2] = v91;
|
|
|
|
vLookDest[1] = v189;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_106;
|
|
|
|
}
|
|
|
|
v170 = this->m_pLookEntity;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v170) {
|
|
|
|
if (!v170->IsSubclassOfSentient()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v188 = v170->centroid[0];
|
|
|
|
v189 = v170->centroid[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v91 = v170->centroid[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_105;
|
|
|
|
}
|
|
|
|
((Sentient *)v170.Pointer())->EyePosition().copyTo(vLookDest);
|
|
|
|
}
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_106:
|
|
|
|
v92 = 0;
|
|
|
|
v93 = angles;
|
2023-10-12 18:19:22 +02:00
|
|
|
do {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v193[0] = 128.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
v156 = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
v193[1] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
v157 = v197[0];
|
|
|
|
v158 = v197[1];
|
|
|
|
v159 = v197[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
v195[1] = v197[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v160 = &v202;
|
2023-10-11 22:49:06 +02:00
|
|
|
v193[2] = 0.0;
|
|
|
|
v195[0] = v197[0];
|
|
|
|
v195[2] = v197[2];
|
2023-10-12 18:19:22 +02:00
|
|
|
while (1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v156 > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
v169 = v167;
|
|
|
|
v159 = v168;
|
|
|
|
v158 = v169;
|
|
|
|
}
|
|
|
|
v195[2] = v168;
|
|
|
|
v195[1] = v167;
|
|
|
|
v195[0] = v157;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
v195[0] = vLookDest[0];
|
|
|
|
v195[1] = vLookDest[1];
|
|
|
|
v195[2] = vLookDest[2];
|
2023-10-12 18:19:22 +02:00
|
|
|
fDist = sqrt(v100);
|
|
|
|
if (fDist >= 0.039999999) {
|
|
|
|
fDist = sqrt(v184 * v184 + v185 * v185 + v186 * v186);
|
2023-10-11 22:49:06 +02:00
|
|
|
fAlpha = ((0.1 - fDist) / 0.060000002);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = 8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = 8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = 8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = 8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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];
|
2023-10-12 18:19:22 +02:00
|
|
|
v179 = -8.0;
|
|
|
|
v180 = -8.0;
|
|
|
|
v181 = -8.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
v104 = &v202;
|
|
|
|
v105 = 0;
|
|
|
|
v106 = v197[1];
|
|
|
|
v107 = v197[2];
|
|
|
|
v108 = v195[0];
|
|
|
|
v109 = v195[1];
|
|
|
|
v110 = v195[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
v193[0] = 0.0;
|
|
|
|
v193[1] = 0.0;
|
|
|
|
v193[2] = -2.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
v174 = v197[0];
|
|
|
|
while (1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v105 > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
v130 = &v202;
|
|
|
|
v131 = 0;
|
|
|
|
v132 = v197[1];
|
|
|
|
v133 = v197[2];
|
|
|
|
v134 = v195[0];
|
|
|
|
v135 = v195[1];
|
|
|
|
v136 = v195[2];
|
2023-10-11 22:49:06 +02:00
|
|
|
v193[0] = 0.0;
|
|
|
|
v193[1] = 2.0;
|
|
|
|
v193[2] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
v175 = v197[0];
|
|
|
|
while (1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v131 > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v171 = edict;
|
2023-10-11 22:49:06 +02:00
|
|
|
v171->s.eyeVector[2] = 0.0;
|
|
|
|
v171->s.eyeVector[1] = 0.0;
|
|
|
|
v171->s.eyeVector[0] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
LocalLookAngles[2] = 0.0;
|
|
|
|
LocalLookAngles[1] = 0.0;
|
|
|
|
LocalLookAngles[0] = 0.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
ACTOR_UPDATEBONECONTROLLERS_5:
|
|
|
|
GetControllerAngles(1).copyTo(v177);
|
|
|
|
torsoAngles[2] = v177[2];
|
|
|
|
torsoAngles[0] = v177[0];
|
|
|
|
torsoAngles[1] = v177[1];
|
|
|
|
GetControllerAngles(0).copyTo(v177);
|
2023-10-12 18:19:22 +02:00
|
|
|
v4 = LocalLookAngles[0];
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[2] = v177[2];
|
|
|
|
headAngles[1] = v177[1];
|
|
|
|
headAngles[0] = v177[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
error = LocalLookAngles[1] - (torsoAngles[1] + v177[1]);
|
|
|
|
v6 = LocalLookAngles[1] - torsoAngles[1];
|
|
|
|
v176 = LocalLookAngles[0] - v177[0];
|
|
|
|
v7 = v6;
|
2023-10-11 22:49:06 +02:00
|
|
|
torsoYawError = v7;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v6 > 180.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v172 = v6 - 360.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_7:
|
|
|
|
torsoYawError = v172;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_8;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v6 < -180.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v172 = v6 + 360.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_7;
|
|
|
|
}
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_8:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (torsoYawError >= 0.0) {
|
|
|
|
if (error < -120.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
error = error + 360.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else if (error > 120.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
error = error - 360.0;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!((((uint8_t)this->m_iLookFlags) ^ 1) & 1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng6 = error;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_25;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (error <= 25.0) {
|
|
|
|
if (-25.0 <= error) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v12 = error;
|
|
|
|
v13 = 0.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_15;
|
|
|
|
}
|
|
|
|
fErr1 = 0.2 * (error + 25.0);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fErr1 = (error - 25.0) * 0.2;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v10 = error;
|
|
|
|
v11 = fErr1;
|
|
|
|
v12 = v10;
|
2023-10-11 22:49:06 +02:00
|
|
|
fDist = v11;
|
2023-10-12 18:19:22 +02:00
|
|
|
v13 = fDist;
|
2023-10-11 22:49:06 +02:00
|
|
|
ACTOR_UPDATEBONECONTROLLERS_15:
|
|
|
|
fErr2 = v12 + headAngles[1];
|
|
|
|
fAng1 = -torsoAngles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
v173 = fErr2;
|
|
|
|
if (fErr2 > fAng1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fErr2 = fAng1;
|
|
|
|
fAng1 = v173;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fErr2 <= v13) {
|
|
|
|
v74 = fAng1;
|
|
|
|
v75 = v13;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng2 = v74;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v75 <= v74) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng2 = v75;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng2 = fErr2;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v17 = level.frametime * 15.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng3 = this->m_fTorsoCurrentTurnSpeed + v17;
|
2023-10-12 18:19:22 +02:00
|
|
|
v19 = this->m_fTorsoCurrentTurnSpeed - v17;
|
|
|
|
if (fAng2 <= fAng3) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng3 = fAng2;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v19 > fAng2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng3 = v19;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
fAng3_ = fAng3;
|
2023-10-11 22:49:06 +02:00
|
|
|
fFrameTorsoDist = level.frametime * this->m_fTorsoMaxTurnSpeed;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-fFrameTorsoDist <= fAng3_) {
|
|
|
|
v72 = fFrameTorsoDist;
|
|
|
|
v73 = fAng3_;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng4 = v72;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v73 <= v72) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng4 = v73;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng4 = -fFrameTorsoDist;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v23 = torsoAngles[1] + fAng4;
|
2023-10-11 22:49:06 +02:00
|
|
|
torsoAngles[1] = v23;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v23 <= 30.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v71 = torsoAngles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
if (torsoAngles[1] >= -30.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng5 = fAng4;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
torsoAngles[1] = -30.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
fAng5 = fAng4 - (v71 + 30.0);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
torsoAngles[1] = 30.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
fAng5 = fAng4 - (v23 - 30.0);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
this->m_fTorsoCurrentTurnSpeed = fAng5;
|
2023-10-12 18:19:22 +02:00
|
|
|
v25 = fAng5;
|
|
|
|
v26 = v12;
|
|
|
|
torsoAngles[0] = 0.0;
|
|
|
|
torsoAngles[2] = 0.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
SetControllerAngles(1, torsoAngles);
|
2023-10-12 18:19:22 +02:00
|
|
|
v4 = LocalLookAngles[0];
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng6 = v26 - v25;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_25:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fAng6 > 15.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v28 = fAng6 - 15.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_27:
|
2023-10-12 18:19:22 +02:00
|
|
|
v29 = level.frametime;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng7 = v28 * 4.0 * v29;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_28;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-15.0 > fAng6) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v28 = fAng6 + 15.0;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_27;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v29 = level.frametime;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng7 = 0.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_28:
|
|
|
|
fAng8 = fAng6;
|
2023-10-12 18:19:22 +02:00
|
|
|
v32 = fAng6;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng9 = -headAngles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v32 > fAng9) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng8 = fAng9;
|
|
|
|
fAng9 = v32;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fAng8 <= fAng7) {
|
|
|
|
if (fAng7 <= fAng9) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v34 = headAngles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
v68 = v29;
|
|
|
|
v69 = fAng9;
|
|
|
|
v34 = headAngles[1];
|
|
|
|
v70 = v69;
|
|
|
|
v29 = v68;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng7 = v70;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng7 = fAng8;
|
2023-10-12 18:19:22 +02:00
|
|
|
v34 = headAngles[1];
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
v35 = this->m_fHeadMaxTurnSpeed;
|
|
|
|
v36 = -(v29 * v35);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v36 <= fAng7) {
|
|
|
|
v67 = fAng7;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng10 = v29 * v35;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v67 <= fAng10) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng10 = v67;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng10 = v36;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v38 = v34;
|
|
|
|
v39 = this->m_fHeadMaxTurnSpeed;
|
|
|
|
v40 = fAng10 + v38;
|
|
|
|
v41 = 60.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[1] = v40;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v40 > 60.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_37;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
v42 = v29;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (headAngles[1] < -60.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v41 = -60.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_37:
|
2023-10-12 18:19:22 +02:00
|
|
|
v43 = v29;
|
|
|
|
v44 = v41;
|
|
|
|
v42 = v43;
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[1] = v44;
|
|
|
|
}
|
|
|
|
v45 = v42;
|
|
|
|
v46 = v4;
|
|
|
|
v47 = v45;
|
|
|
|
v48 = fabs(v46);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v48 >= 15.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng11 = 15.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
fDist = v48;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng11 = fDist;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v176 > fAng11) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v50 = v176 - fAng11;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_42:
|
2023-10-12 18:19:22 +02:00
|
|
|
fDist = 0.2 * v50;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng12 = fDist;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_43;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-fAng11 > v176) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v50 = fAng11 + v176;
|
|
|
|
goto ACTOR_UPDATEBONECONTROLLERS_42;
|
|
|
|
}
|
|
|
|
fAng12 = 0.0;
|
|
|
|
ACTOR_UPDATEBONECONTROLLERS_43:
|
|
|
|
v52 = fAng12;
|
|
|
|
v53 = v47;
|
|
|
|
v54 = v52;
|
|
|
|
v55 = v39 * v53;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-v55 <= v52) {
|
|
|
|
v65 = v55;
|
|
|
|
v66 = v54;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng13 = v65;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v66 <= v65) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng13 = v66;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng13 = -v55;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
v57 = fAng13 + headAngles[0];
|
|
|
|
v58 = 35.0;
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[0] = v57;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v57 > 35.0 || (v58 = -35.0, headAngles[0] < -35.0)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[0] = v58;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
headAngles[2] = 0.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (this->m_iLookFlags & 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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];
|
2023-10-12 18:19:22 +02:00
|
|
|
v59 = m_vLUpperArmDesiredAngles[1] - v180;
|
|
|
|
v60 = v59;
|
|
|
|
if (v59 <= 180.0) {
|
|
|
|
if (v59 < -180.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v60 = v59 + 360.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
v60 = v59 - 360.0;
|
|
|
|
}
|
|
|
|
v61 = this->m_fLUpperArmTurnSpeed * level.frametime;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-v61 <= v60) {
|
|
|
|
v63 = v61;
|
|
|
|
v64 = v60;
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng15 = v63;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v64 <= v63) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng15 = v64;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fAng15 = -v61;
|
|
|
|
}
|
|
|
|
v178[0] = this->m_vLUpperArmDesiredAngles[0];
|
|
|
|
v178[1] = fAng15 + v177[1];
|
|
|
|
v178[2] = 0.0;
|
|
|
|
SetControllerAngles(2, v178);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
2023-10-12 18:19:22 +02:00
|
|
|
if ((org - origin).lengthSquared() > Square(1024)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
bRejoin = true;
|
|
|
|
DisbandSquadMate(this);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (level.Spawned()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SafeSetOrigin(org);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
setOrigin(org);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vHome = origin;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (bRejoin) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//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-12 18:19:22 +02:00
|
|
|
void Actor::SafeSetOrigin(vec3_t newOrigin)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (newOrigin == origin) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (!m_bNoPlayerCollision) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (p && IsTouching(p)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::DoMove(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
mmove_t mm;
|
|
|
|
//FIXME: macros
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bDoPhysics && m_iOriginTime != level.inttime && !m_pGlueMaster && !bindmaster) {
|
|
|
|
switch (m_eAnimMode) {
|
|
|
|
case 1: //normal i guess ?
|
|
|
|
{
|
|
|
|
SetMoveInfo(&mm);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
VectorCopy2D(frame_delta, mm.desired_dir);
|
|
|
|
float frameDeltaLen = VectorNormalize2D(mm.desired_dir);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
mm.desired_speed = frameDeltaLen / level.frametime;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm.desired_speed > m_maxspeed) {
|
|
|
|
mm.desired_speed = m_maxspeed;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
MmoveSingle(&mm);
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
case 2: //path
|
|
|
|
{
|
|
|
|
MovePath(frame_delta.length() / level.frametime);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
case 3: //path_goal (end) ?
|
|
|
|
{
|
|
|
|
MovePathGoal(frame_delta.length() / level.frametime);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
case 4: //dest
|
|
|
|
{
|
|
|
|
MoveDest(frame_delta.length() / level.frametime);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
case 6: //noclip
|
|
|
|
{
|
|
|
|
SafeSetOrigin(frame_delta + origin);
|
|
|
|
velocity = frame_delta / level.frametime;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
2023-10-12 18:19:22 +02:00
|
|
|
case 7: //falling path
|
|
|
|
{
|
|
|
|
SafeSetOrigin(m_pFallPath->pos[m_pFallPath->currentPos]);
|
|
|
|
m_pFallPath->currentPos++;
|
|
|
|
velocity = vec_zero;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateAngles(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float max_change, error, dist;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_YawAchieved) {
|
2023-10-11 22:49:06 +02:00
|
|
|
error = m_DesiredYaw - angles[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
if (error <= 180) {
|
|
|
|
if (error < -180.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
error += 360;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
error -= 360;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist = m_fAngleYawSpeed * level.frametime;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-dist <= error) {
|
2023-10-11 22:49:06 +02:00
|
|
|
max_change = dist;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (error <= dist) {
|
2023-10-11 22:49:06 +02:00
|
|
|
max_change = error;
|
|
|
|
StopTurning();
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
max_change = -dist;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
setAngles(Vector {0, angles[1] + max_change, 0});
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +02:00
|
|
|
void Actor::SetLeashHome(Vector vHome)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bFixedLeash) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
Vector Actor::GunPosition(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iGunPositionCheckTime < level.inttime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iGunPositionCheckTime = level.inttime;
|
2023-10-12 18:19:22 +02:00
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
if (weap) {
|
2023-10-11 22:49:06 +02:00
|
|
|
weap->GetMuzzlePosition(m_vGunPosition);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::CanSee(Entity *e1, float fov, float vision_distance, bool bNoEnts)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
bool canSee = Sentient::CanSee(e1, fov, vision_distance, false);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (e1 == m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyVisibleCheckTime = level.inttime;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (canSee) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetEnemyPos(e1->origin);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bEnemyIsDisguised = m_Enemy->m_bIsDisguised;
|
|
|
|
m_iEnemyCheckTime = level.inttime;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iLastEnemyVisibleTime = level.inttime;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (canSee != m_bEnemyVisible) {
|
|
|
|
m_bEnemyVisible = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyVisibleChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fov != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyFovCheckTime = level.inttime;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (canSee != m_bEnemyInFOV) {
|
|
|
|
m_bEnemyInFOV = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyFovChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return canSee;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::InFOV
|
|
|
|
|
|
|
|
Returns true if positin is within fov.
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::CanShoot(Entity *ent)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
bool bCanShootEnemy = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ent->IsSubclassOfSentient()) {
|
|
|
|
Sentient *sen = (Sentient *)ent;
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro.
|
2023-10-12 18:19:22 +02:00
|
|
|
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)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
if (G_SightTrace(
|
2023-10-12 18:19:22 +02:00
|
|
|
GunPosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
sen->centroid,
|
|
|
|
this,
|
|
|
|
sen,
|
|
|
|
MASK_CANSEE,
|
|
|
|
qfalse,
|
|
|
|
"Actor::CanShoot centroid"
|
|
|
|
)
|
|
|
|
|| G_SightTrace(
|
2023-10-11 22:49:06 +02:00
|
|
|
GunPosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
sen->EyePosition(),
|
|
|
|
this,
|
|
|
|
sen,
|
|
|
|
MASK_CANSEE,
|
|
|
|
qfalse,
|
2023-10-12 18:19:22 +02:00
|
|
|
"Actor::CanShoot eyes"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
bCanShootEnemy = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
|
|
|
m_bCanShootEnemy = bCanShootEnemy;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iCanShootCheckTime = level.inttime;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)) {
|
|
|
|
if (CanSeeFrom(GunPosition(), ent)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
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"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::EnemyInFOV(int iMaxDirtyTime)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyFovCheckTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
bool bInFov = InFOV(m_Enemy->centroid, m_fFov, m_fFovDot);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bEnemyInFOV != bInFov) {
|
|
|
|
m_bEnemyInFOV = !m_bEnemyInFOV;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEnemyFovChangeTime = level.inttime;
|
|
|
|
}
|
|
|
|
m_iEnemyFovCheckTime = level.inttime;
|
|
|
|
}
|
|
|
|
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-12 18:19:22 +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
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyVisibleCheckTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
CanSee(m_Enemy, 0, 0.828 * world->farplane_distance, false);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::CanShootEnemy(int iMaxDirtyTime)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +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
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
bool Actor::FriendlyInLineOfFire(Entity *other)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
// FIXME: unimplemented
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
Vector Actor::VirtualEyePosition()
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
// FIXME: unimplemented
|
|
|
|
return Vector();
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::FireWeapon(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Sentient::FireWeapon(WEAPON_MAIN, FIRE_PRIMARY);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::IsMachineGunnerState(int state)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
return true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::IsDogState(int state)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (fRadius == 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fRadius = m_fSight;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_fSight <= fRadius) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fRadius = m_fSight;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ent) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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::CanTarget
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor can target.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::CanTarget(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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-12 18:19:22 +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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::ShowInfo(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::ShowInfo(float fDot, float fDist)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fMaxDist, fMinDot;
|
2023-10-11 22:49:06 +02:00
|
|
|
static cvar_t *g_entinfo_max;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!bEntinfoInit) {
|
2023-10-11 22:49:06 +02:00
|
|
|
g_entinfo_max = gi.Cvar_Get("g_entinfo_max", "2048", 0);
|
2023-10-12 18:19:22 +02:00
|
|
|
bEntinfoInit = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
fMinDot = 0.9f;
|
2023-10-11 22:49:06 +02:00
|
|
|
fMaxDist = g_entinfo_max->value;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsKilledState(m_ThinkState)) {
|
|
|
|
fMinDot = 0.99f;
|
2023-10-11 22:49:06 +02:00
|
|
|
fMaxDist = 512;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (g_entinfo->integer != 4) {
|
|
|
|
if (fDot <= fMinDot) {
|
|
|
|
if (fDot <= 0 || fDist >= 256) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fMaxDist <= fDist || fDist <= 64) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 74;
|
|
|
|
|
|
|
|
G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "DISABLED");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 56;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "%i:%i:%s:%.1f", entnum, radnum, targetname.c_str(), health);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
m_PotentialEnemies.GetCurrentThreat()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsCuriousState(m_ThinkState)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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(),
|
2023-10-12 18:19:22 +02:00
|
|
|
m_PotentialEnemies.GetCurrentVisibility() * 100
|
|
|
|
);
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector a = origin;
|
|
|
|
a.z += maxs.z + 20;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
G_DebugString(a, 1.0, 1.0, 1.0, 1.0, "%s", ThinkStateName().c_str());
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
sAnimThreadFile.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (g_entinfo->integer == 1) {
|
|
|
|
if (m_pGrenade) {
|
2023-10-11 22:49:06 +02:00
|
|
|
G_DebugLine(m_pGrenade->origin, m_vGrenadePos, 1.0, 0.0, 0.0, 1.0);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
G_DebugCircle(centroid, m_fMinDistance, 1.0, 0.0, 0.0, 1.0, qtrue);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
str Actor::ThinkName(void) const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
return Director.GetString(m_csThinkNames[m_Think[m_ThinkLevel]]);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
str Actor::ThinkStateName(void) const
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::MoveTo(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
m_csPatrolCurrentAnim = ev->GetConstString(1);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsVectorAt(2)) {
|
|
|
|
Vector vec = ev->GetVector(2);
|
|
|
|
SetPatrolCurrentNode(vec);
|
|
|
|
} else {
|
|
|
|
SetPatrolCurrentNode(ev->GetListener(2));
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode) {
|
|
|
|
m_vScriptGoal = origin;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ClearAimNode(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_aimNode) {
|
|
|
|
if (m_aimNode->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::SetAimNode(Listener *l)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearAimNode();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l) {
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError(
|
|
|
|
"Bad aim node with classname '%s' specified for '%s' at (%f %f %f)\n",
|
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
2023-10-12 18:19:22 +02:00
|
|
|
origin.z
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::AimAt(Event *ev)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsVectorAt(1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector orig = ev->GetVector(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_aimNode) {
|
|
|
|
if (m_aimNode->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
delete m_aimNode;
|
|
|
|
}
|
|
|
|
m_aimNode = NULL;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
TempWaypoint *twp = new TempWaypoint;
|
|
|
|
m_aimNode = twp;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_aimNode->setOrigin(orig);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetAimNode(ev->GetListener(1));
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::LookAtLookEntity(void)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector dir;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pLookEntity->IsSubclassOfSentient()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = ((Sentient *)m_pLookEntity.Pointer())->EyePosition() - EyePosition();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::IdleLook(void)
|
2018-08-19 08:26:59 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pLookEntity) {
|
2023-10-11 22:49:06 +02:00
|
|
|
LookAtLookEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::IdleLook(vec3_t dir)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pLookEntity) {
|
2023-10-11 22:49:06 +02:00
|
|
|
LookAtLookEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ClearLookEntity(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pLookEntity) {
|
|
|
|
if (m_pLookEntity->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::LookAt(const Vector& vec)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (g_showlookat->integer == entnum || g_showlookat->integer == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf(
|
|
|
|
"Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
vec.x,
|
|
|
|
vec.y,
|
2023-10-12 18:19:22 +02:00
|
|
|
vec.z
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
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();
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::LookAt
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
Change current look entity.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::LookAt(Listener *l)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ClearLookEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l) {
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
|
|
|
ScriptError(
|
|
|
|
"Bad look entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z
|
2023-10-12 18:19:22 +02:00
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l != this) {
|
|
|
|
l = (SimpleEntity *)l;
|
|
|
|
if (g_showlookat->integer == entnum || g_showlookat->integer == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf(
|
|
|
|
"Script lookat: %i %i %s looking at point %.0f %.0f %.0f\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
2023-10-12 18:19:22 +02:00
|
|
|
((SimpleEntity *)l)->origin.x,
|
|
|
|
((SimpleEntity *)l)->origin.y,
|
|
|
|
((SimpleEntity *)l)->origin.z
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pLookEntity = (SimpleEntity *)l;
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +02:00
|
|
|
void Actor::EventLookAt(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsVectorAt(1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
LookAt(ev->GetVector(1));
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
LookAt(ev->GetListener(1));
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::IdlePoint(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pPointEntity) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector delta = m_pPointEntity->centroid - origin;
|
|
|
|
Vector v2;
|
|
|
|
VectorNormalize(delta);
|
|
|
|
v2 = delta.toAngles();
|
|
|
|
|
|
|
|
float yaw = AngleNormalize180(v2[1] - angles[1] + 30);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (yaw > 100) {
|
2023-10-11 22:49:06 +02:00
|
|
|
yaw = 100;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (yaw < -80) {
|
2023-10-11 22:49:06 +02:00
|
|
|
yaw = -80;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vLUpperArmDesiredAngles[0] = v2[0];
|
|
|
|
m_vLUpperArmDesiredAngles[1] = yaw;
|
|
|
|
m_vLUpperArmDesiredAngles[2] = v2[2];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ClearPointEntity(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pPointEntity) {
|
|
|
|
if (m_pPointEntity->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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();
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pPointEntity = twp;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::PointAt(Listener *l)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ClearPointEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l) {
|
|
|
|
if (l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
|
|
|
ScriptError(
|
|
|
|
"Bad point entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
2023-10-12 18:19:22 +02:00
|
|
|
origin.z
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l != this) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventPointAt(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsVectorAt(1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
PointAt(ev->GetVector(1));
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::IdleTurn(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pTurnEntity) {
|
|
|
|
for (int i = 0; i <= 1; i++) {
|
|
|
|
if (m_pTurnEntity == this) {
|
2023-10-11 22:49:06 +02:00
|
|
|
StopTurning();
|
|
|
|
m_pTurnEntity = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vec2_t facedir;
|
|
|
|
VectorSub2D(m_pTurnEntity->centroid, origin, facedir);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (facedir[0] || facedir[1]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (error >= m_fTurnDoneError + 0.001 || -(m_fTurnDoneError + 0.001) >= error) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (m_pTurnEntity == prevTurnEntity) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ClearTurnEntity(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pTurnEntity) {
|
|
|
|
if (m_pTurnEntity->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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();
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pTurnEntity = twp;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::TurnTo(Listener *l)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearTurnEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l) {
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
|
|
|
ScriptError(
|
|
|
|
"Bad turn entity with classname '%s' specified for '%s' at (%f %f %f)\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
2023-10-12 18:19:22 +02:00
|
|
|
origin.z
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pTurnEntity = (SimpleEntity *)l;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventTurnTo(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsVectorAt(1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
TurnTo(ev->GetVector(1));
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fTurnDoneError < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGiveWeaponInternal(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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (giveItem(weapName)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unholster();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventGiveWeapon
|
|
|
|
|
|
|
|
Give weapon to actor.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGiveWeapon(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
2023-10-12 18:19:22 +02:00
|
|
|
str weapName = ev->GetString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (csWeapName == STRING_MG42) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
glbs.Printf(
|
|
|
|
"EventGiveWeapon script: %s weapName: %s \n",
|
|
|
|
Director.GetString(STRING_GLOBAL_WEAPON_SCR).c_str(),
|
|
|
|
weapName.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
ExecuteScript(&e1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-17 23:50:38 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventGetWeapon
|
|
|
|
|
|
|
|
Returns weapon path to script.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetWeapon(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-12 18:19:22 +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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bEnablePain) {
|
2023-10-11 22:49:06 +02:00
|
|
|
e1.AddConstString(STRING_GLOBAL_PAIN_SCR);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 1; i <= ev->NumArgs(); i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
e1.AddValue(ev->GetValue(i));
|
|
|
|
}
|
|
|
|
ExecuteScript(&e1);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkState(THINKSTATE_PAIN, THINKLEVEL_PAIN);
|
|
|
|
|
|
|
|
RaiseAlertness(0.5);
|
|
|
|
|
|
|
|
m_PainTime = level.inttime;
|
|
|
|
|
|
|
|
Entity *ent = ev->GetEntity(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ent && ent->IsSubclassOfSentient() && !IsTeamMate((Sentient *)ent)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pLastAttacker = ent;
|
|
|
|
|
|
|
|
m_iCuriousLevel = 9;
|
|
|
|
|
|
|
|
//FIXME: macro
|
|
|
|
SetCuriousAnimHint(7);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bEnableEnemy && m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->Pain) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->Pain)(ev);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
health = 0.0;
|
|
|
|
if (bPlayDeathAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_KILLED_SCR);
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 1; i < ev->NumArgs(); i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
e1.AddValue(ev->GetValue(i));
|
|
|
|
}
|
|
|
|
ExecuteScript(&e1);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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]];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->Killed) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->Killed)(ev, bPlayDeathAnim);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetEnemy(NULL, false);
|
|
|
|
|
|
|
|
DisbandSquadMate(this);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (bPlayDeathAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (p1) {
|
|
|
|
if (p1->IsSubclassOfPlayer() && p1->m_Team == m_Team) {
|
2023-10-11 22:49:06 +02:00
|
|
|
p1->m_iNumEnemiesKilled++;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (p1->IsSubclassOfSentient()) {
|
|
|
|
for (Sentient *pSent = level.m_HeadSentient[m_Team]; pSent; pSent = pSent->m_NextSentient) {
|
|
|
|
if (pSent != this) {
|
|
|
|
if (pSent->IsSubclassOfActor()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
NotifySquadmateKilled(pSent, p1);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::DeathEmbalm(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (maxs[2] > 8) {
|
2023-10-11 22:49:06 +02:00
|
|
|
maxs[2] -= 4;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (maxs[2] > 8) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Actor_DeathEmbalm);
|
|
|
|
PostEvent(e1, 0.5);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::PlayAttachedAnimation
|
|
|
|
|
|
|
|
Play attached animation
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::PlayAttachedAnimation(Event *ev)
|
|
|
|
{
|
|
|
|
Event e1(EV_Listener_ExecuteScript);
|
|
|
|
e1.AddConstString(STRING_GLOBAL_ANIM_ATTACHED_SCR);
|
|
|
|
e1.AddValue(ev->GetValue(1));
|
|
|
|
ExecuteScript(&e1);
|
|
|
|
}
|
|
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (fMoveSpeed > m_maxspeed) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fMoveSpeed = m_maxspeed;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::MovePath(float fMoveSpeed)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
mmove_t mm;
|
|
|
|
|
|
|
|
SetMoveInfo(&mm);
|
|
|
|
|
|
|
|
mm.desired_speed = fMoveSpeed;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm.desired_speed > m_maxspeed) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_speed = m_maxspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Path.UpdatePos(origin);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ai_debugpath->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
for (PathInfo *current_path = m_Path.CurrentNode(); current_path != m_Path.LastNode();
|
|
|
|
current_path = m_Path.NextNode()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!mm.hit_obstacle) {
|
|
|
|
if (m_WallDir) {
|
|
|
|
if (level.inttime >= m_iWallDodgeTimeout) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_WallDir = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0
|
|
|
|
&& CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = -m_WallDir;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
velocity.copyTo(mm.velocity);
|
|
|
|
origin.copyTo(mm.origin);
|
|
|
|
mm.groundPlane = m_groundPlane;
|
2023-10-12 18:19:22 +02:00
|
|
|
mm.walking = m_walking;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_groundPlaneNormal.copyTo(mm.groundPlaneNormal);
|
|
|
|
VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal);
|
|
|
|
|
|
|
|
m_Path.UpdatePos(mm.hit_origin);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_Path.NextNode()) {
|
|
|
|
if (!m_WallDir) {
|
2023-10-11 22:49:06 +02:00
|
|
|
auto dir = m_Path.CurrentDelta();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Path.NextNode()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = m_Path.NextNode()->dir;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = 1;
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = -1;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!mm.hit_obstacle) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
m_WallDir = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!(m_Path.NextNode() && m_Path.NextNode()->bAccurate && m_Path.IsSide())) {
|
|
|
|
if (m_WallDir) {
|
|
|
|
if (m_WallDir < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm.hit_obstacle) {
|
|
|
|
m_WallDir = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
auto dir = m_Path.CurrentDelta();
|
2023-10-11 22:49:06 +02:00
|
|
|
auto pNextNode = m_Path.NextNode();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pNextNode) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = pNextNode->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = pNextNode->point[1] - mm.hit_origin[0];
|
|
|
|
vDelta[1] = pNextNode->point[0] - mm.hit_origin[1];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (DotProduct2D(dir, vDelta) >= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float fCross = CrossProduct2D(dir, vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fCross <= -16) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (fCross >= 16) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
MmoveSingle(&mm);
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_WallDir) {
|
2023-10-11 22:49:06 +02:00
|
|
|
auto dir = m_Path.CurrentDelta();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Path.NextNode()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = m_Path.NextNode()->dir;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (dir[1] * mm.obstacle_normal[0] < dir[0] * mm.obstacle_normal[1]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = 1;
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = -1;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!mm.hit_obstacle) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
m_WallDir = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_WallDir < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm.hit_obstacle) {
|
|
|
|
m_WallDir = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iWallDodgeTimeout = 0;
|
|
|
|
}
|
|
|
|
GetMoveInfo(&mm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_iWallDodgeTimeout = level.inttime + 1000;
|
|
|
|
|
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
auto dir = m_Path.CurrentDelta();
|
2023-10-11 22:49:06 +02:00
|
|
|
auto pNextNode = m_Path.NextNode();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pNextNode) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = pNextNode->dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = pNextNode->point[1] - mm.hit_origin[0];
|
|
|
|
vDelta[1] = pNextNode->point[0] - mm.hit_origin[1];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDelta[0] * dir[1] <= vDelta[1] * dir[0]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = -mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = 1;
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
m_WallDir = -1;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
MmoveSingle(&mm);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mm.hit_obstacle) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorCopy(velocity, mm.velocity);
|
|
|
|
VectorCopy(origin, mm.origin);
|
|
|
|
mm.groundPlane = m_groundPlane;
|
2023-10-12 18:19:22 +02:00
|
|
|
mm.walking = m_walking;
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorCopy(m_groundPlaneNormal, mm.groundPlaneNormal);
|
|
|
|
|
|
|
|
VectorCopy2D(mm.obstacle_normal, m_PrevObstacleNormal);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_WallDir == char(-1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mm.desired_dir[0] = -mm.obstacle_normal[1];
|
|
|
|
mm.desired_dir[1] = mm.obstacle_normal[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::MovePathGoal(float fMoveSpeed)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fTimeToGo, fDeltaSquareLen, fSlowdownSpeed;
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2_t vDelta;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_Path.HasCompleteLookahead()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MovePath(fMoveSpeed);
|
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fTimeToGo = m_fPathGoalTime - level.time;
|
|
|
|
|
|
|
|
VectorSub2D(origin, m_Path.LastNode()->point, vDelta);
|
|
|
|
|
|
|
|
fDeltaSquareLen = VectorLength2DSquared(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fTimeToGo <= -0.001) {
|
|
|
|
if (fDeltaSquareLen < (Square(fMoveSpeed * Square(0.5)))) {
|
|
|
|
fTimeToGo = 0.5;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fPathGoalTime = level.time + fTimeToGo;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csPathGoalEndAnimScript == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csPathGoalEndAnimScript = STRING_ANIM_IDLE_SCR;
|
|
|
|
}
|
|
|
|
m_bStartPathGoalEndAnim = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
MovePath(fMoveSpeed);
|
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fSlowdownSpeed = sqrt(fDeltaSquareLen) * (2 / (fTimeToGo + level.frametime));
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fSlowdownSpeed > fMoveSpeed + 0.001 && fSlowdownSpeed > 0.4 * sv_runspeed->value) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fPathGoalTime = 0;
|
|
|
|
StartAnimation(3, m_Anim);
|
|
|
|
MovePath(fMoveSpeed);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
MovePath(fSlowdownSpeed);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.time >= m_fPathGoalTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csMood > STRING_ALERT) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventDamagePuff(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (speed <= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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
|
|
|
}
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fov < 0 || fov > 360) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("fov must be in the range [0,360]");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fFov = fov;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ClearPatrolCurrentNode(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode) {
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::NextPatrolCurrentNode(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bScriptGoalValid) {
|
|
|
|
if (m_patrolCurrentNode->origin == m_vScriptGoal) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bScriptGoalValid = false;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPatrolCurrentNode();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::SetPatrolCurrentNode(Vector& vec)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPatrolCurrentNode();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
TempWaypoint *twp = new TempWaypoint();
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::SetPatrolCurrentNode(Listener *l)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPatrolCurrentNode();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (l && !l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
|
|
|
ScriptError(
|
|
|
|
"Bad patrol path with classname '%s' specified for '%s' at (%f %f %f)\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
l->getClassname(),
|
|
|
|
targetname.c_str(),
|
|
|
|
origin.x,
|
|
|
|
origin.y,
|
|
|
|
origin.z
|
2023-10-12 18:19:22 +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
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::ShowInfo_PatrolCurrentNode(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("current patrol node: %s\n", m_patrolCurrentNode->targetname.c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ShowInfo_AimNode(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_aimNode) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("aim node: %s\n", m_aimNode->targetname.c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::MoveOnPathWithSquad(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fDistSquared, fIntervalSquared;
|
|
|
|
vec2_t vMyNormalDir, vDelta, vHisDir;
|
2023-10-11 22:49:06 +02:00
|
|
|
Player *p;
|
|
|
|
|
|
|
|
//FIXMEL: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime < m_iSquadStandTime + 500 || !PathExists() || PathComplete()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fIntervalSquared = Square(m_fInterval);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iSquadStandTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fIntervalSquared *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = (Player *)G_GetEntity(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (IsTeamMate(p)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorSub2D(p->origin, origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fIntervalSquared > fDistSquared && DotProduct2D(vDelta, PathDelta()) > 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorSub2D(velocity, p->velocity, vMyNormalDir);
|
|
|
|
VectorNormalize2D(vMyNormalDir);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) < 2304) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iSquadStandTime = level.inttime;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (Actor *pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this;
|
|
|
|
pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) {
|
|
|
|
if (!pSquadMate->IsSubclassOfActor()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
VectorSub2D(pSquadMate->origin, origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared >= fIntervalSquared || DotProduct2D(vDelta, PathDelta()) <= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pSquadMate->PathExists() || pSquadMate->PathComplete()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorCopy2D(pSquadMate->velocity, vHisDir);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (VectorLength2DSquared(vHisDir) <= 8) {
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorCopy2D(pSquadMate->PathDelta(), vHisDir);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (DotProduct2D(PathDelta(), vHisDir) >= 0
|
|
|
|
&& (entnum == pSquadMate->entnum || DotProduct2D(vHisDir, vDelta) >= 0)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::MoveToWaypointWithPlayer(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fIntervalSquared, fDistSquared;
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2_t vMyNormalDir, vDelta, vMyDir;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime < m_iSquadStandTime + 500) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
fIntervalSquared = Square(m_fInterval);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iSquadStandTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fIntervalSquared += fIntervalSquared;
|
|
|
|
}
|
|
|
|
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsTeamMate(p)) {
|
|
|
|
vDelta[0] = p->origin[0] - origin[0];
|
|
|
|
vDelta[1] = p->origin[1] - origin[1];
|
2023-10-11 22:49:06 +02:00
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared >= fIntervalSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vMyDir[0] = m_patrolCurrentNode->origin[0] - origin[0];
|
|
|
|
vMyDir[1] = m_patrolCurrentNode->origin[1] - origin[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
if (DotProduct2D(vDelta, vMyDir) < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iSquadStandTime = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vMyNormalDir[0] = velocity[0] - p->velocity[0];
|
|
|
|
vMyNormalDir[1] = velocity[1] - p->velocity[1];
|
|
|
|
VectorNormalize2D(vMyNormalDir);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared - DotProduct2D(vDelta, vMyNormalDir) > 2304) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::PatrolNextNodeExists(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode) {
|
|
|
|
if (m_patrolCurrentNode->IsSubclassOfTempWaypoint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
if (fabs(origin[0] - m_patrolCurrentNode->origin[0]) < 16.0
|
2023-10-12 18:19:22 +02:00
|
|
|
&& fabs(origin[1] - m_patrolCurrentNode->origin[1]) < 16.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
next = true;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (PathExists() && PathComplete()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
next = true;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (next) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::MoveToPatrolCurrentNode(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
UpdatePatrolCurrentNode();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode && !m_bPatrolWaitTrigger) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector delta;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_patrolCurrentNode->IsSubclassOfWaypoint()) {
|
|
|
|
if (MoveToWaypointWithPlayer()) {
|
|
|
|
m_bNextForceStart = false;
|
|
|
|
m_eNextAnimMode = 4;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csNextAnimString = m_csPatrolCurrentAnim;
|
|
|
|
FaceMotion();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Stand();
|
|
|
|
IdleLook();
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDest(m_patrolCurrentNode->origin);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMoveDoneRadiusSquared == 0.0 || m_patrolCurrentNode->Next()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
delta = m_patrolCurrentNode->origin - origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
SimpleActor::SetPath(m_patrolCurrentNode->origin, "Actor::MoveToPatrolCurrentNode", 0, NULL, 0);
|
|
|
|
if (!PathExists()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
IdleLook();
|
|
|
|
|
|
|
|
Anim_Idle();
|
|
|
|
parm.movefail = qtrue;
|
|
|
|
return false;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (MoveOnPathWithSquad()) {
|
|
|
|
if (PatrolNextNodeExists()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eNextAnimMode = 2;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eNextAnimMode = 3;
|
|
|
|
}
|
|
|
|
m_csNextAnimString = m_csPatrolCurrentAnim;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNextForceStart = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
FaceMotion();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Stand();
|
|
|
|
IdleLook();
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMoveDoneRadiusSquared == 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (PathComplete()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_Path.HasCompleteLookahead() || m_patrolCurrentNode->Next()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (m_fMinDistance < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistance = 0;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ Warning: mindist negative, forcing to %g for entity %i, targetname '%s'\n",
|
|
|
|
m_fMinDistance,
|
|
|
|
entnum,
|
2023-10-12 18:19:22 +02:00
|
|
|
targetname.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
m_fMinDistanceSquared = m_fMinDistance * m_fMinDistance;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetMinDistance(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(m_fMinDistance);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetMaxDistance(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_fMaxDistance = ev->GetFloat(1);
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMaxDistance < 256) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDistance = 256;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ Warning: maxdist too small, forcing to %g for entity %i, targetname '%s'\n",
|
|
|
|
m_fMaxDistance,
|
|
|
|
entnum,
|
2023-10-12 18:19:22 +02:00
|
|
|
targetname.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::EventGetLeash(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(m_fLeash);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetLeash(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fLeash = ev->GetFloat(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fLeashSquared = Square(m_fLeash);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetInterval(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(m_fInterval);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetInterval(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_fInterval = ev->GetFloat(1);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventDistToEnemy(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float dist = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector distV = origin - m_Enemy->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
dist = distV.length();
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::Init(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
g_showinfo = gi.Cvar_Get("g_showinfo", "0", 0);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs[i].PassesTransitionConditions = NULL;
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs[i].ShowInfo = NULL;
|
|
|
|
GlobalFuncs[i].ReceiveAIEvent = &Actor::DefaultReceiveAIEvent;
|
|
|
|
GlobalFuncs[i].IsState = NULL;
|
|
|
|
GlobalFuncs[i].PathnodeClaimRevoked = NULL;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (developer->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
int currTime = m_iEyeUpdateTime;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (currLvlTime > currTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iEyeUpdateTime = NextUpdateTime(currTime, 100);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
GetTag("eyes bone", &eyeTag, &m_vEyeDir);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
eyeposition = eyeTag - origin;
|
|
|
|
|
|
|
|
m_vEyeDir[2] = 0.0;
|
|
|
|
VectorNormalizeFast(m_vEyeDir);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[0] < -10.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[0] = -10.5;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[0] > 10.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[0] = 10.5;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[1] < -10.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[1] = -10.5;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[1] > 10.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[1] = 10.5;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[2] < 4.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[2] = 4.5;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (eyeposition[2] > 89.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
eyeposition[2] = 89.5;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +02:00
|
|
|
bool Actor::RequireThink(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (G_GetEntity(0)) {
|
|
|
|
return (level.inttime < edict->r.lastNetTime + 60000);
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +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::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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateEnemyInternal(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (Sentient *pSent = level.m_HeadSentient[1 - m_Team]; pSent; pSent = pSent->m_NextSentient) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_PotentialEnemies.AddPotentialEnemy(pSent);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_PotentialEnemies.CheckEnemies(this);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (m_Enemy != m_PotentialEnemies.GetCurrentEnemy()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetEnemy(m_PotentialEnemies.GetCurrentEnemy(), false);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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-12 18:19:22 +02:00
|
|
|
if (m_fNoticeTimeScale > m_fMaxNoticeTimeScale) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fNoticeTimeScale = m_fMaxNoticeTimeScale;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateEnemy(int iMaxDirtyTime)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime > iMaxDirtyTime + m_iEnemyCheckTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateEnemyInternal();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::DetectSmokeGrenades
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::DetectSmokeGrenades(void)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::SetEnemy(Sentient *pEnemy, bool bForceConfirmed)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pEnemy == m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Enemy->m_iAttackerCount--;
|
|
|
|
}
|
|
|
|
m_bNewEnemy = m_Enemy == NULL;
|
|
|
|
//delete m_Enemy;
|
|
|
|
|
|
|
|
m_Enemy = pEnemy;
|
|
|
|
|
|
|
|
m_iEnemyChangeTime = level.inttime;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_Actor_ShareEnemy);
|
|
|
|
//FIXME: macro
|
|
|
|
PostEvent(e1, 0.75);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy->m_bHasDisguise) {
|
|
|
|
if (level.inttime > m_iEnemyVisibleCheckTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//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++;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (bForceConfirmed) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::SetEnemyPos(Vector vPos)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_vLastEnemyPos != vPos) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iLastEnemyPosChangeTime = level.inttime;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_vLastEnemyPos = vPos;
|
|
|
|
mTargetPos = m_vLastEnemyPos;
|
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mTargetPos += m_Enemy->eyeposition;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
mTargetPos.z += 88;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mTargetPos.z - EyePosition().z < 128) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//"anim slot weight flagged"
|
2023-10-12 18:19:22 +02:00
|
|
|
int numArgs = ev->NumArgs(), slot = 0, animnum;
|
|
|
|
float weight = 1;
|
2023-10-11 22:49:06 +02:00
|
|
|
const_str anim, flagVal;
|
2023-10-12 18:19:22 +02:00
|
|
|
qboolean flagged = qfalse;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
//FIXME: better notation, but this works for now.
|
2023-10-12 18:19:22 +02:00
|
|
|
if (numArgs < 1 || numArgs > 4) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (numArgs == 1) {
|
|
|
|
anim = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (numArgs == 2) {
|
|
|
|
anim = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
slot = ev->GetInteger(2);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (slot > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (numArgs == 3) {
|
2023-10-11 22:49:06 +02:00
|
|
|
weight = ev->GetFloat(3);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weight < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Negative anim weight not allowed");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weight != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
slot = ev->GetInteger(2);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (slot > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
anim = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (numArgs == 4) {
|
2023-10-11 22:49:06 +02:00
|
|
|
flagVal = ev->GetConstString(4);
|
|
|
|
flagged = qtrue;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flagVal != STRING_FLAGGED) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("unknown keyword '%s', expected 'flagged'", Director.GetString(flagVal).c_str());
|
|
|
|
}
|
|
|
|
weight = ev->GetFloat(3);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weight < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Negative anim weight not allowed");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weight != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
slot = ev->GetInteger(2);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (slot > 2) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Bad animation slot, only 0 and 1 supported");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
anim = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (!slot) {
|
2023-10-11 22:49:06 +02:00
|
|
|
flagged = qtrue;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flagged) {
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.motionfail = qtrue;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelMotionAnim) {
|
|
|
|
if (slot) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_weightType[GetMotionSlot(slot)] = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
}
|
|
|
|
StartMotionAnimSlot(slot, animnum, weight);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flagged) {
|
|
|
|
m_iMotionSlot = GetMotionSlot(slot);
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.motionfail = qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventEndActionAnim
|
|
|
|
|
|
|
|
End action animation.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventEndActionAnim(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.upperfail = qtrue;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelActionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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");
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
str animstr = Director.GetString(anim);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, animstr.c_str());
|
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(animstr.c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
gi.DPrintf("Actor::EventSetMotionAnim %s %d\n", animstr.c_str(), animnum);
|
|
|
|
parm.motionfail = qtrue;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelMotionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
StartMotionAnimSlot(0, animnum, 1.0);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iMotionSlot = GetMotionSlot(0);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAimMotionAnim(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
int anim_crouch, anim_stand, anim_high;
|
2023-10-11 22:49:06 +02:00
|
|
|
const_str name;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs() != 3) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: maybe inline func ?
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
name = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
anim_crouch = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (anim_crouch == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
name = ev->GetConstString(2);
|
2023-10-11 22:49:06 +02:00
|
|
|
anim_stand = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (anim_stand == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
name = ev->GetConstString(3);
|
2023-10-11 22:49:06 +02:00
|
|
|
anim_high = gi.Anim_NumForName(edict->tiki, Director.GetString(name).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (anim_high == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(name).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
|
|
|
parm.motionfail = qtrue;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelMotionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeMotionAnim();
|
|
|
|
m_bMotionAnimSet = true;
|
|
|
|
UpdateAimMotion();
|
|
|
|
StartAimMotionAnimSlot(0, anim_crouch);
|
|
|
|
StartAimMotionAnimSlot(1, anim_stand);
|
|
|
|
StartAimMotionAnimSlot(2, anim_high);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iMotionSlot = GetMotionSlot(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetActionAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs() != 3) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fAimLimit_down = ev->GetFloat(2);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fAimLimit_down > 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fAimLimit_down = -0.001f;
|
|
|
|
ScriptError("Positive lower_limit not allowed");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fAimLimit_up = ev->GetFloat(3);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fAimLimit_up <= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fAimLimit_up = 0.001f;
|
|
|
|
ScriptError("Negative upper_limit not allowed");
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim).c_str(), edict->tiki);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
const_str anim2 = ev->GetConstString(2);
|
|
|
|
int animnum2 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim2));
|
|
|
|
if (animnum2 == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim2).c_str(), edict->tiki);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
const_str anim3 = ev->GetConstString(3);
|
|
|
|
int animnum3 = gi.Anim_NumForName(edict->tiki, Director.GetString(anim3));
|
|
|
|
if (animnum3 == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UnknownAnim(Director.GetString(anim3).c_str(), edict->tiki);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.upperfail = qtrue;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelActionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bAimAnimSet = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bActionAnimSet = true;
|
|
|
|
UpdateAim();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
StartAimAnimSlot(0, animnum);
|
|
|
|
StartAimAnimSlot(1, anim2);
|
|
|
|
StartAimAnimSlot(2, anim3);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iActionSlot = GetActionSlot(0);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventUpperAnim(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs()) {
|
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_bLevelActionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetUpperAnim(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
const_str anim = ev->GetConstString(1);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(anim).c_str());
|
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLevelActionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
StartActionAnimSlot(animnum);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iActionSlot = SimpleActor::GetActionSlot(0);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeSayAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bSayAnimSet = true;
|
|
|
|
m_iSaySlot = -2;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bLevelSayAnim = bLevelSayAnim;
|
|
|
|
|
|
|
|
Com_Printf(
|
|
|
|
"Couldn't find animation '%s' in '%s' - trying sound alias instead.\n",
|
|
|
|
Director.GetString(name).c_str(),
|
2023-10-12 18:19:22 +02:00
|
|
|
edict->tiki->a->name
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventIdleSayAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
const_str name;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs()) {
|
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState <= THINKSTATE_ATTACK || IsGrenadeState(m_ThinkState)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csSayAnim = name;
|
|
|
|
//FIXME: macro
|
|
|
|
m_bNextLevelSayAnim = 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (!SoundSayAnim(name, 1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csSayAnim = name;
|
|
|
|
//FIXME: macro
|
|
|
|
m_bNextLevelSayAnim = 1;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_bLevelSayAnim == 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSayAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
const_str name;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->NumArgs()) {
|
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState <= THINKSTATE_KILLED || !SoundSayAnim(name, 2)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_bLevelSayAnim == 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetSayAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
const_str name;
|
2023-10-12 18:19:22 +02:00
|
|
|
str sName;
|
|
|
|
if (ev->NumArgs() != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("bad number of arguments");
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bLevelSayAnim == 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
name = ev->GetConstString(1);
|
|
|
|
|
|
|
|
parm.sayfail = qtrue;
|
2023-10-12 18:19:22 +02:00
|
|
|
sName = Director.GetString(name);
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, sName.c_str());
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
Com_Printf("EventSetSayAnim sName: %s, animnum: %d, mVoiceType: %d\n", sName.c_str(), animnum, mVoiceType);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!SoundSayAnim(name, m_bLevelSayAnim)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
int flags = gi.Anim_FlagsSkel(edict->tiki, animnum);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flags & TAF_HASUPPER) {
|
|
|
|
if (m_bLevelActionAnim) {
|
|
|
|
if (!m_bSayAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iSaySlot = m_iActionSlot;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flags & TAF_HASDELTA) {
|
|
|
|
if (m_bLevelMotionAnim) {
|
|
|
|
if (!m_bSayAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iSaySlot = m_iMotionSlot;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ChangeActionAnim();
|
|
|
|
ChangeMotionAnim();
|
|
|
|
StartMotionAnimSlot(0, animnum, 1.0);
|
|
|
|
|
|
|
|
m_iMotionSlot = m_iActionSlot = GetMotionSlot(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
|
|
|
m_bActionAnimSet = true;
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
m_iActionSlot = GetActionSlot(0);
|
|
|
|
}
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iSaySlot = m_iActionSlot;
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
|
2023-10-12 18:19:22 +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
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pAnimThread) {
|
|
|
|
if (g_scripttrace->integer) {
|
|
|
|
if (m_pAnimThread->CanScriptTracePrint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("--- Change Anim\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pAnimThread->AbortRegistration(STRING_EMPTY, this);
|
|
|
|
ScriptClass *sc = m_pAnimThread->GetScriptClass();
|
|
|
|
if (sc) {
|
2023-10-11 22:49:06 +02:00
|
|
|
delete sc;
|
|
|
|
}
|
|
|
|
Com_Printf("ChangeAnim: m_pAnimThread aborted\n");
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState != 4) // THINKSTATE_ATTACK
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState <= 4) // THINKSTATE_ATTACK
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState >= 2) // THINKSTATE_PAIN
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bMotionAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iMotionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (m_bActionAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iActionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
v3 = m_bSayAnimSet == 0;
|
|
|
|
LABEL_13:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v3) {
|
2023-10-11 22:49:06 +02:00
|
|
|
goto LABEL_14;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
goto LABEL_20;
|
|
|
|
}
|
|
|
|
goto LABEL_21;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState != 7) // m_ThinkState != THINKSTATE_GRENADE
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
LABEL_21:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bMotionAnimSet) {
|
|
|
|
if (!m_bLevelMotionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iMotionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bActionAnimSet) {
|
|
|
|
if (!m_bLevelActionAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iActionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bSayAnimSet && !m_bLevelSayAnim) {
|
2023-10-11 22:49:06 +02:00
|
|
|
LABEL_20:
|
|
|
|
AnimFinished(m_iSaySlot, true);
|
|
|
|
goto LABEL_14;
|
|
|
|
}
|
|
|
|
goto LABEL_14;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bMotionAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iMotionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (m_bActionAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnimFinished(m_iActionSlot, true);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (m_bSayAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v3 = m_bLevelSayAnim == 2;
|
|
|
|
goto LABEL_13;
|
|
|
|
}
|
|
|
|
LABEL_14:
|
|
|
|
m_fCrossblendTime = 0.5;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_pAnimThread = m_Anim.Create(this);
|
|
|
|
if (m_pAnimThread) {
|
|
|
|
if (g_scripttrace->integer) {
|
|
|
|
if (m_pAnimThread->CanScriptTracePrint()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("+++ Change Anim\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
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-12 18:19:22 +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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateSayAnim(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 1\n");
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState > THINKSTATE_KILLED) {
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 2\n");
|
|
|
|
int animnum = gi.Anim_NumForName(edict->tiki, Director.GetString(m_csSayAnim).c_str());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum == -1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 3\n");
|
|
|
|
|
|
|
|
int flags = gi.Anim_FlagsSkel(edict->tiki, animnum);
|
|
|
|
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flags & 256) {
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 4\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (flags & ANIM_NOACTION) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeMotionAnim();
|
|
|
|
|
|
|
|
StartMotionAnimSlot(0, animnum, 1);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
|
|
|
m_bLevelMotionAnim = true;
|
|
|
|
|
|
|
|
m_iMotionSlot = m_iActionSlot = GetMotionSlot(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bActionAnimSet = true;
|
|
|
|
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
|
|
|
|
|
|
|
m_iActionSlot = GetActionSlot(0);
|
|
|
|
}
|
|
|
|
ChangeSayAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bSayAnimSet = true;
|
|
|
|
m_bLevelSayAnim = m_bNextLevelSayAnim;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNextLevelSayAnim = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iSaySlot = m_iActionSlot;
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 4\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_bNextLevelSayAnim == 2 || (!IsAttackState(m_ThinkState) && !IsGrenadeState(m_ThinkState))) {
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 6\n");
|
|
|
|
ChangeSayAnim();
|
|
|
|
m_bSayAnimSet = true;
|
|
|
|
StartSayAnimSlot(animnum);
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bLevelSayAnim = m_bNextLevelSayAnim;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNextLevelSayAnim = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iSaySlot = GetSaySlot();
|
2023-10-11 22:49:06 +02:00
|
|
|
gi.DPrintf("Actor::UpdateSayAnim 7\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bSayAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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());
|
2023-10-12 18:19:22 +02:00
|
|
|
if (animnum != -1) {
|
|
|
|
if (IsAttackState(m_ThinkState) || IsGrenadeState(m_ThinkState) || IsKilledState(m_ThinkState)
|
|
|
|
|| IsPainState(m_ThinkState)) {
|
|
|
|
if (!m_bActionAnimSet) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unregister(STRING_UPPERANIMDONE);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bActionAnimSet = true;
|
|
|
|
|
|
|
|
StartActionAnimSlot(animnum);
|
|
|
|
|
|
|
|
m_bLevelActionAnim = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iActionSlot = SimpleActor::GetActionSlot(0);
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateAnim(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_bAnimating = true;
|
|
|
|
SimpleActor::UpdateAim();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (SimpleActor::UpdateSelectedAnimation()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("ChangeAnim\n");
|
|
|
|
ChangeAnim();
|
|
|
|
}
|
|
|
|
Director.Unpause();
|
|
|
|
Director.Pause();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csSayAnim != STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateSayAnim();
|
|
|
|
m_csSayAnim = STRING_EMPTY;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csUpperAnim != STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UpdateUpperAnim();
|
|
|
|
m_csUpperAnim = STRING_EMPTY;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bSayAnimSet && !m_bDog) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SimpleActor::UpdateEmotion();
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int slot = 0; slot < 14; slot++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: better notation
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!((m_bUpdateAnimDoneFlags >> slot) & 1)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SimpleActor::UpdateAnimSlot(slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float fAnimTime, fAnimWeight, total_weight = 0, time = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int slot = 0; slot < 14; slot++) {
|
|
|
|
if ((m_weightType[slot] == 1 || m_weightType[slot] == 4) && animFlags[slot] & ANIM_LOOP) {
|
2023-10-11 22:49:06 +02:00
|
|
|
UseSyncTime(slot, 1);
|
2023-10-12 18:19:22 +02:00
|
|
|
fAnimTime = AnimTime(slot);
|
2023-10-11 22:49:06 +02:00
|
|
|
fAnimWeight = edict->s.frameInfo[slot].weight;
|
|
|
|
time += fAnimTime * fAnimWeight;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (std::isinf(time)) {
|
|
|
|
Com_Printf(
|
|
|
|
"ent %i, targetname '%s', anim '%s', slot %i, fAnimTime %f, fAnimWeight %f\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
entnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
AnimName(slot),
|
|
|
|
slot,
|
|
|
|
fAnimTime,
|
2023-10-12 18:19:22 +02:00
|
|
|
fAnimWeight
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
total_weight += fAnimWeight;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
UseSyncTime(slot, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (total_weight != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::Think(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
int v1, v2, v3, tempHistory, ohIndex;
|
|
|
|
m_bAnimating = false;
|
|
|
|
if (g_ai->integer && m_bDoAI && edict->tiki) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//gi.DPrintf("Actor::Think 1\n");
|
|
|
|
Director.iPaused++;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
v1 = level.inttime;
|
|
|
|
v2 = v1 / 125;
|
|
|
|
v3 = v1 / 125;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v1 / 125 < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v3 = v2 + 3;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
tempHistory = v2 - (v3 & 0xFFFFFFFC);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iCurrentHistory != tempHistory) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iCurrentHistory = tempHistory;
|
2023-10-12 18:19:22 +02:00
|
|
|
ohIndex = tempHistory - 1;
|
|
|
|
if (ohIndex < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ohIndex = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy2D(origin, m_vOriginHistory[ohIndex]);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bNoPlayerCollision) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Entity *ent = G_GetEntity(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!IsTouching(ent)) {
|
|
|
|
Com_Printf(
|
|
|
|
"(entnum %d, radnum %d) is going solid after not getting stuck in the player\n", entnum, radnum
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
setSolidType(SOLID_BBOX);
|
|
|
|
m_bNoPlayerCollision = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//gi.DPrintf("Actor::Think 2\n");
|
|
|
|
m_eNextAnimMode = -1;
|
|
|
|
FixAIParameters();
|
|
|
|
UpdateEnableEnemy();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pTetherEnt) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vHome = m_pTetherEnt->origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
//gi.DPrintf("Actor::Think 3\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bBecomeRunner) {
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.movefail = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkMap[THINKSTATE_IDLE] != THINK_RUNNER && m_ThinkMap[THINKSTATE_IDLE] != THINK_PATROL) {
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.movefail = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bDirtyThinkState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDirtyThinkState = false;
|
|
|
|
ThinkStateTransitions();
|
|
|
|
}
|
|
|
|
|
|
|
|
//gi.DPrintf("Actor::Think 4\n");
|
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->ThinkState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->ThinkState)();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNeedReload = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
mbBreakSpecialAttack = false;
|
|
|
|
Director.Unpause();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
//gi.DPrintf("Actor::Think 5: entnum %d, classname: %s\n", entnum, G_GetEntity(0) ? G_GetEntity(0)->getClassname() : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::CheckUnregister(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bBecomeRunner = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (parm.movefail) {
|
2023-10-11 22:49:06 +02:00
|
|
|
parm.movedone = false;
|
|
|
|
Unregister(STRING_MOVEDONE);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unregister(STRING_HASENEMY);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bEnemyVisible) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::PostThink(bool bDontFaceWall)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
CheckUnregister();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (bDontFaceWall) {
|
|
|
|
if (!m_pTurnEntity || m_ThinkState != THINKSTATE_IDLE) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::AnimFinished(int slot, bool stop)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (stop && slot >= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
animFlags[slot] |= ANIM_NOACTION;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (slot == m_iMotionSlot) {
|
|
|
|
if (stop) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bLevelMotionAnim = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iMotionSlot = -1;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
MPrintf("flagged anim finished slot %d\n", slot);
|
|
|
|
Unregister(STRING_FLAGGEDANIMDONE);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (slot == m_iActionSlot) {
|
|
|
|
if (stop) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeActionAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (m_csUpperAnim == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MPrintf("upper anim finished slot %d\n", slot);
|
|
|
|
Unregister(STRING_UPPERANIMDONE);
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (slot == m_iSaySlot) {
|
|
|
|
if (stop) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ChangeSayAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (m_csSayAnim == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MPrintf("say anim finished slot %d\n", slot);
|
|
|
|
//gi.DPrintf("unregister STRING_SAYDONE\n");
|
|
|
|
Unregister(STRING_SAYDONE);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (slot == GetSaySlot() && stop) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkState == state) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bDirtyThinkState = true;
|
2023-10-12 18:19:22 +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::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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
switch (think_idle) {
|
2023-10-11 22:49:06 +02:00
|
|
|
case THINK_PATROL:
|
|
|
|
case THINK_RUNNER:
|
|
|
|
m_bBecomeRunner = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
think_curious = THINK_CURIOUS;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
while (m_csThinkNames[result] != csName) {
|
|
|
|
if (++result > NUM_THINKS - 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::SetThinkState(eThinkState state, eThinkLevel level)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsAttackState(state)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csIdleMood = STRING_NERVOUS;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkMap[THINKSTATE_ATTACK] != THINK_ALARM && m_ThinkMap[THINKSTATE_ATTACK] != THINK_WEAPONLESS
|
|
|
|
&& m_ThinkMap[THINKSTATE_ATTACK] != THINK_DOG_ATTACK && !GetWeapon(WEAPON_MAIN)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
targetname.c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_ATTACK, THINK_WEAPONLESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ThinkStates[level] = state;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level >= m_ThinkLevel) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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::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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::ClearThinkStates(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i <= NUM_THINKLEVELS - 1; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkState(THINKSTATE_VOID, (eThinkLevel)i);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAlarmNode(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Listener *l = ev->GetListener(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l) {
|
|
|
|
if (!l->inheritsFrom(&SimpleEntity::ClassInfo)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("Alarm node must be an entity");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_AlarmNode = (SimpleEntity *)l;
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 19:21:41 +02:00
|
|
|
void Actor::EventSetPreAlarmThread(Event *ev)
|
|
|
|
{
|
|
|
|
if (ev->IsFromScript()) {
|
|
|
|
m_PreAlarmThread.SetThread(ev->GetValue());
|
|
|
|
} else {
|
|
|
|
m_PreAlarmThread.Set(ev->GetString(1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAlarmThread(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsFromScript()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_AlarmThread.SetThread(ev->GetValue());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_AlarmThread.Set(ev->GetString(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetAlarmThread(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_AlarmThread.GetScriptValue(&ev->GetValue());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::EventGetSoundAwareness(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(m_fSoundAwareness);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetGrenadeAwareness(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_fGrenadeAwareness = ev->GetFloat(1);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetGrenadeAwareness(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(m_fGrenadeAwareness);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetTypeIdle(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeIdle %s : %d\n", ev->GetString(1).c_str(), think);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_IDLE)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetTypeAttack(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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.
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_ATTACK)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventGetTypeAttack(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddConstString(m_csThinkNames[m_ThinkMap[THINKSTATE_ATTACK]]);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetTypeDisguise(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeDisguise %s : %d\n", ev->GetString(1).c_str(), think);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_DISGUISE)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetDisguiseAcceptThread(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ev->IsFromScript()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_DisguiseAcceptThread.SetThread(ev->GetValue());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_DisguiseAcceptThread.Set(ev->GetString(1));
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetDisguiseAcceptThread(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_DisguiseAcceptThread.GetScriptValue(&ev->GetValue());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::EventSetDisguiseLevel(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_iDisguiseLevel = ev->GetInteger(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iDisguiseLevel - 1 > 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventGetDisguiseLevel(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddInteger(m_iDisguiseLevel);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetTypeGrenade(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
eThinkNum think = (eThinkNum)GetThinkType(ev->GetConstString(1));
|
|
|
|
glbs.Printf("EventSetTypeGrenade %s : %d\n", ev->GetString(1).c_str(), think);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!Actor::GlobalFuncs[think].IsState(THINKSTATE_GRENADE)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_GRENADE, THINK_GRENADE);
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
ScriptError(
|
|
|
|
"Invalid grenade think '%s'", Director.GetString(m_csThinkNames[m_ThinkMap[THINKSTATE_GRENADE]]).c_str()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThink(THINKSTATE_GRENADE, think);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetTypeGrenade(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::InitThinkStates(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (size_t i = 0; i < NUM_THINKSTATES; i++) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_ThinkMap[i] = THINK_VOID;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
for (size_t i = 0; i < NUM_THINKLEVELS; i++) {
|
|
|
|
m_Think[i] = THINK_VOID;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_ThinkStates[i] = THINKSTATE_VOID;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_ThinkMap[THINKSTATE_DISGUISE] = THINK_DISGUISE_SALUTE;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_ThinkMap[THINKSTATE_GRENADE] = THINK_GRENADE;
|
|
|
|
m_ThinkMap[THINKSTATE_NOCLIP] = THINK_NOCLIP;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
m_ThinkLevel = THINKLEVEL_NORMAL;
|
|
|
|
m_ThinkState = THINKSTATE_VOID;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::DefaultRestart(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
EndState(m_ThinkLevel);
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::SuspendState(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ResumeState(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::BeginState(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->BeginState) {
|
|
|
|
(this->*func->BeginState)();
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EndState(int level)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[level]];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
m_Think[level] = THINK_VOID;
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->EndState) {
|
|
|
|
(this->*func->EndState)();
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::RestartState(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::UpdateEnableEnemy(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bEnableEnemy != m_bDesiredEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bEnableEnemy = m_bDesiredEnableEnemy;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bDesiredEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetLeashHome(origin);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (m_ThinkStates[THINKLEVEL_NORMAL] <= THINKSTATE_DISGUISE) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::ThinkStateTransitions(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
int newThinkLevel;
|
|
|
|
int newThinkState;
|
|
|
|
|
|
|
|
//GlobalFuncs_t *func;// = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
|
|
|
|
|
|
|
//loop on all think levels.
|
2023-10-12 18:19:22 +02:00
|
|
|
for (newThinkLevel = NUM_THINKLEVELS - 1; newThinkLevel >= 0; newThinkLevel--) {
|
2023-10-11 22:49:06 +02:00
|
|
|
newThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
//a new think level is found if it's think state is not THINKSTATE_VOID
|
2023-10-12 18:19:22 +02:00
|
|
|
if (newThinkState != THINKSTATE_VOID) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_ThinkMap[newThinkState] == m_Think[m_ThinkLevel]) {
|
|
|
|
if (newThinkLevel != m_ThinkLevel || m_ThinkState != newThinkState) {
|
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = (eThinkState)newThinkState;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[newThinkState];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
RestartState();
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (newThinkLevel > THINKLEVEL_NORMAL) {
|
|
|
|
for (int i = 0; i < newThinkLevel; i++) {
|
|
|
|
if (m_ThinkStates[i] == THINKSTATE_VOID) {
|
2023-10-11 22:49:06 +02:00
|
|
|
EndState(i);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (newThinkLevel > m_ThinkLevel) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SuspendState();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
EndState(m_ThinkLevel);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (newThinkLevel == m_ThinkLevel) {
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Think[newThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_ThinkLevel = (eThinkLevel)newThinkLevel;
|
|
|
|
m_ThinkState = m_ThinkStates[newThinkLevel];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Think[newThinkLevel] != m_ThinkMap[m_ThinkState]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
EndState(newThinkLevel);
|
|
|
|
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
|
|
|
|
|
|
|
BeginState();
|
|
|
|
m_Think[m_ThinkLevel] = m_ThinkMap[m_ThinkState];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::FixAIParameters(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: needs revision(silly mistakes)
|
|
|
|
|
|
|
|
float distmin, distmin2, distmax;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pTetherEnt) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float leash = 64;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pTetherEnt->IsSubclassOfEntity()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
leash = m_pTetherEnt->angles.y - m_pTetherEnt->origin.y + m_pTetherEnt->angles.z + m_pTetherEnt->origin.z;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (leash <= m_fLeash) {
|
2023-10-11 22:49:06 +02:00
|
|
|
distmin = m_fLeash;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): increasing leash from %g to %g.\n"
|
2023-10-11 22:49:06 +02:00
|
|
|
"^~^~^ 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,
|
2023-10-12 18:19:22 +02:00
|
|
|
leash
|
|
|
|
);
|
|
|
|
m_fLeash = leash;
|
|
|
|
distmin = leash;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fLeashSquared = Square(leash);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
distmin = m_fLeash;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMinDistance <= distmin) {
|
2023-10-11 22:49:06 +02:00
|
|
|
distmax = m_fMinDistance;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to match "
|
|
|
|
"leash.\n"
|
2023-10-11 22:49:06 +02:00
|
|
|
"^~^~^ 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,
|
2023-10-12 18:19:22 +02:00
|
|
|
distmin
|
|
|
|
);
|
|
|
|
m_fMinDistance = distmin;
|
|
|
|
distmax = distmin;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistanceSquared = distmin * distmin;
|
|
|
|
}
|
|
|
|
distmax += 128;
|
2023-10-12 18:19:22 +02:00
|
|
|
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"
|
2023-10-11 22:49:06 +02:00
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
m_fMaxDistance,
|
|
|
|
distmax,
|
2023-10-12 18:19:22 +02:00
|
|
|
128
|
|
|
|
);
|
|
|
|
|
|
|
|
m_fMaxDistance = distmax;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDistanceSquared = distmax * distmax;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (world->farplane_distance > 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro and floats
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMaxDistance > world->farplane_distance * 0.828 + 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf(
|
2023-10-12 18:19:22 +02:00
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing maxdist from %g to %g to be %g%% "
|
|
|
|
"of farplane.\n"
|
2023-10-11 22:49:06 +02:00
|
|
|
"^~^~^ 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,
|
2023-10-12 18:19:22 +02:00
|
|
|
2.0
|
|
|
|
);
|
|
|
|
distmin2 = m_fMinDistance;
|
|
|
|
m_fMaxDistance = world->farplane_distance * 0.828;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDistanceSquared = m_fMaxDistance * m_fMaxDistance;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (distmin2 + 128.0 - 1.0 > m_fMaxDistance) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf(
|
2023-10-12 18:19:22 +02:00
|
|
|
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): reducing mindist from %g to %g to be "
|
|
|
|
"less than maxdist "
|
2023-10-11 22:49:06 +02:00
|
|
|
"after fog adjustment.\n"
|
|
|
|
"\n",
|
|
|
|
entnum,
|
|
|
|
radnum,
|
|
|
|
targetname.c_str(),
|
|
|
|
distmin2,
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fMaxDistance <= 128 ? 0 : m_fMaxDistance - 128
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistance = m_fMaxDistance - 128.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMaxDistance - 128.0 < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMinDistance = 0.0;
|
|
|
|
}
|
|
|
|
m_fMinDistanceSquared = Square(m_fMinDistance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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::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-12 18:19:22 +02:00
|
|
|
bool Actor::AttackEntryAnimation(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
|
|
|
if (level.inttime >= level.m_iAttackEntryAnimTime + 3000) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float distSq = (m_Enemy->origin - origin).lengthXYSquared();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pSquadMate == this) {
|
|
|
|
if (m_bNewEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
m_bNoSurprise = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNewEnemy = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vec2_t vDelta;
|
|
|
|
vDelta[0] = m_Enemy->origin.x - origin.x;
|
|
|
|
vDelta[1] = m_Enemy->origin.y - origin.y;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDelta[0] != 0 || vDelta[1] != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYawDir(vDelta);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredLookDir(m_Enemy->origin - origin);
|
|
|
|
|
|
|
|
m_csNextAnimString = STRING_ANIM_STANDIDENTIFY_SCR;
|
|
|
|
|
|
|
|
m_bNextForceStart = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNoSurprise = true;
|
|
|
|
m_bNewEnemy = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (rand() > distSq * 0.0026041667) //rand() / 0x17F
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macro
|
|
|
|
StartAnimation(1, STRING_ANIM_STANDSHOCK_SCR);
|
|
|
|
m_bNoSurprise = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNewEnemy = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bNewEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Say(STRING_ANIM_SAY_SIGHTED_SCR, 200, false);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
m_bNoSurprise = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_bNewEnemy = false;
|
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::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-12 18:19:22 +02:00
|
|
|
void Actor::CheckForThinkStateTransition(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL)) {
|
|
|
|
if (!m_bEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
CheckForTransition(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (!CheckForTransition(THINKSTATE_ATTACK, THINKLEVEL_NORMAL)) {
|
|
|
|
if (!CheckForTransition(THINKSTATE_DISGUISE, THINKLEVEL_NORMAL)) {
|
|
|
|
if (CheckForTransition(THINKSTATE_CURIOUS, THINKLEVEL_NORMAL)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pszDebugState = "from_sight";
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (m_ThinkStates[level] != state) {
|
|
|
|
func = &GlobalFuncs[m_ThinkMap[state]];
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->PassesTransitionConditions && (this->*(func->PassesTransitionConditions))()) {
|
|
|
|
SetThinkState(state, THINKLEVEL_NORMAL);
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
|
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 ?
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Grenade(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_bLockThinkState && m_bEnableEnemy && m_pGrenade) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::PassesTransitionConditions_BadPlace
|
|
|
|
|
|
|
|
Should actor transition think state to bad place?
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
bool Actor::PassesTransitionConditions_BadPlace(void)
|
|
|
|
{
|
|
|
|
if (m_bLockThinkState) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_iBadPlaceIndex != 0;
|
|
|
|
}
|
|
|
|
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (m_bLockThinkState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy && !(m_Enemy->flags & FL_NOTARGET)) {
|
|
|
|
if (EnemyIsDisguised()) {
|
|
|
|
return true;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_PotentialEnemies.GetCurrentVisibility() > 0.999f) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
2023-10-12 18:19:22 +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
|
|
|
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 ?
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Disguise(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bLockThinkState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_iNextDisguiseTime > level.inttime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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-12 18:19:22 +02:00
|
|
|
if (!m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (EnemyIsDisguised()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_PotentialEnemies.GetCurrentVisibility() > 0.999f) {
|
|
|
|
if (fabs(m_Enemy->origin[2] - origin[2]) <= 48.0f) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2_t delta;
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (fHorzDistanceSquared > Square(32) && fHorzDistanceSquared < m_fMaxDisguiseDistSquared) {
|
|
|
|
Player *player = (Player *)G_GetEntity(0);
|
|
|
|
Vector pos = EyePosition();
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
return G_SightTrace(
|
|
|
|
pos,
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
player->centroid,
|
|
|
|
this,
|
|
|
|
player,
|
|
|
|
MASK_TRANSITION,
|
|
|
|
qfalse,
|
2023-10-12 18:19:22 +02:00
|
|
|
"Actor::PassesTransitionConditions_Disguise"
|
|
|
|
);
|
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_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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (m_bLockThinkState) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_Enemy && m_iCuriousTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(6);
|
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy && !EnemyIsDisguised() && m_PotentialEnemies.GetCurrentVisibility() <= 0.999f) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//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
|
|
|
}
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
bool Actor::PassesTransitionConditions_Idle(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
glbs.Printf("PassesTransitionConditions_Idle\n");
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
UpdateEnemy(500);
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bLockThinkState) {
|
|
|
|
return false;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_Enemy && !m_iCuriousTime) {
|
|
|
|
return true;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetRunAnim(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddConstString(GetRunAnim());
|
|
|
|
}
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::FaceEnemyOrMotion(int iTimeIntoMove)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vDelta = origin - m_vLastEnemyPos;
|
2023-10-12 18:19:22 +02:00
|
|
|
vDelta.z = 0;
|
|
|
|
if (iTimeIntoMove > 999) {
|
|
|
|
if (m_Path.CurrentNodeIndex() != m_sCurrentPathNodeIndex) {
|
|
|
|
float fDist = PathDistanceAlongVector(vDelta);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bFaceEnemy = fDist <= 0 || vDelta.lengthXYSquared() * Square(64) >= Square(fDist);
|
|
|
|
|
|
|
|
m_sCurrentPathNodeIndex = m_Path.CurrentNodeIndex();
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bFaceEnemy = true;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bFaceEnemy && (vDelta.x >= 15.0 || vDelta.x <= -15.0 || vDelta.y >= 15.0 || vDelta.y <= -15.0)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vDelta.x = -vDelta.x;
|
|
|
|
vDelta.y = -vDelta.y;
|
|
|
|
FaceDirectionDuringMotion(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::FaceDirectionDuringMotion(vec3_t vLook)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float yaw;
|
|
|
|
|
|
|
|
SetDesiredLookDir(vLook);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (velocity[0] != 0 || velocity[1] != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float fMagsSquared = VectorLength2DSquared(vLook) * VectorLength2DSquared(velocity);
|
2023-10-12 18:19:22 +02:00
|
|
|
float fDot = DotProduct2D(velocity, vLook);
|
|
|
|
float fDotSquared = Square(fDot);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
yaw = velocity.toYaw();
|
|
|
|
|
|
|
|
float fYaw2;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fMagsSquared * 0.5 < fDotSquared) {
|
|
|
|
if (fDot >= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 = yaw;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (yaw - 180 >= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 = yaw - 180;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 = yaw - 180 + 360;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (vLook[0] * velocity[1] <= vLook[1] * velocity[0]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 = yaw - 270;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 = yaw - 90;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fYaw2 < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fYaw2 += 360;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYaw(fYaw2);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYawDir(vLook);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetAnimName(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddConstString(m_csAnimName);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAnimName(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_csAnimName = ev->GetConstString(1);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetDisguiseRange(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float range = ev->GetFloat(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxDisguiseDistSquared = Square(range);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetDisguiseRange(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddFloat(sqrt(m_fMaxDisguiseDistSquared));
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetDisguisePeriod(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_iDisguisePeriod = ev->GetFloat(1) * 1000 + 0.5;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetDisguisePeriod(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::FaceMotion(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector delta;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (VectorLength2DSquared(velocity) > 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vec3_t dir;
|
|
|
|
velocity.copyTo(dir);
|
|
|
|
delta = origin - m_vOriginHistory[m_iCurrentHistory];
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (delta.lengthXYSquared() >= 1) {
|
|
|
|
if (DotProduct2D(velocity, delta) > 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
delta.copyTo(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsIdleState(m_ThinkState)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
IdleLook(dir);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredLookDir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetDesiredYawDir(dir);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (IsIdleState(m_ThinkState) && m_pLookEntity) {
|
2023-10-11 22:49:06 +02:00
|
|
|
LookAtLookEntity();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::ForceAttackPlayer(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, (Sentient *)G_GetEntity(0));
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!pPlayer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("player doesn't exist");
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventShareEnemy(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +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) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::EventShareGrenade(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
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)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (originator != this && originator != GetActiveWeapon(WEAPON_MAIN)) {
|
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-12 18:19:22 +02:00
|
|
|
if (func->ReceiveAIEvent) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->ReceiveAIEvent)(event_origin, iType, originator, fDistSquared, fMaxDistSquared);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +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::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-12 18:19:22 +02:00
|
|
|
void Actor::DefaultReceiveAIEvent(
|
|
|
|
vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared
|
|
|
|
)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!IsDead()) {
|
|
|
|
if (!originator->IsDead() && originator->IsSubclassOfSentient() && ((Sentient *)originator)->m_Team == m_Team
|
|
|
|
&& !IsSquadMate((Sentient *)originator)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MergeWithSquad((Sentient *)originator);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
switch (iType) {
|
2023-10-11 22:49:06 +02:00
|
|
|
case AI_EVENT_WEAPON_FIRE:
|
|
|
|
case AI_EVENT_WEAPON_IMPACT:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Square(m_fHearing) > fDistSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
WeaponSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
case AI_EVENT_EXPLOSION:
|
|
|
|
case AI_EVENT_MISC:
|
|
|
|
case AI_EVENT_MISC_LOUD:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Square(m_fHearing) > fDistSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
CuriousSound(iType, event_origin, fDistSquared, fMaxDistSquared);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
case AI_EVENT_AMERICAN_VOICE:
|
|
|
|
case AI_EVENT_GERMAN_VOICE:
|
|
|
|
case AI_EVENT_AMERICAN_URGENT:
|
|
|
|
case AI_EVENT_GERMAN_URGENT:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Square(m_fHearing) > fDistSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VoiceSound(iType, event_origin, fDistSquared, fMaxDistSquared, originator);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
case AI_EVENT_FOOTSTEP:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Square(m_fHearing) > fDistSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
FootstepSound(event_origin, fDistSquared, fMaxDistSquared, originator);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
case AI_EVENT_GRENADE:
|
|
|
|
GrenadeNotification(originator);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
int Actor::PriorityForEventType(int iType)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
switch (iType) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//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:
|
2023-10-12 18:19:22 +02:00
|
|
|
assert(!"PriorityForEventType: unknown ai_event type");
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::CuriousSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float v7, v8, fRangeFactor = 1.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
int iPriority;
|
|
|
|
if (m_bEnableEnemy) {
|
|
|
|
if (m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE
|
|
|
|
|| m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: name variables.
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fMaxDistSquared != 0.0) {
|
|
|
|
v7 = 1 * (1.0 / 3) - fDistSquared * (1 * (1.0 / 3)) / fMaxDistSquared;
|
|
|
|
if (v7 <= 1.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fRangeFactor = v7;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
v8 = fRangeFactor * m_fSoundAwareness;
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (v8 >= rand() * 0.000000046566129) {
|
2023-10-11 22:49:06 +02:00
|
|
|
RaiseAlertnessForEventType(iType);
|
|
|
|
iPriority = PriorityForEventType(iType);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (iPriority >= m_iCuriousLevel) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iCuriousLevel = iPriority;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (iType == AI_EVENT_WEAPON_IMPACT) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared <= Square(192)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else if (iType > AI_EVENT_WEAPON_IMPACT) {
|
|
|
|
if (iType == AI_EVENT_EXPLOSION) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared <= Square(768)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(3);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(5);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (iType == AI_EVENT_WEAPON_FIRE) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared <= Square(512)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(2);
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetCuriousAnimHint(5);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEnemyPos(sound_origin);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::WeaponSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Sentient *pOwner;
|
|
|
|
gi.Printf("Actor::WeaponSound");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (originator->IsSubclassOfWeapon()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
pOwner = ((Weapon *)originator)->GetOwner();
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (!originator->IsSubclassOfProjectile()) {
|
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
pOwner = ((Projectile *)originator)->GetOwner();
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!pOwner) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Sentient *pEnemy;
|
|
|
|
|
|
|
|
pEnemy = pOwner->m_Enemy;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pOwner->m_Team == m_Team) {
|
|
|
|
if (!pEnemy) {
|
|
|
|
if (pOwner->IsSubclassOfActor()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Actor *pAOwner = (Actor *)pOwner;
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (originator->IsSubclassOfWeapon() && pAOwner->m_Think[0] == THINK_MACHINEGUNNER) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Weapon *pWOriginator = (Weapon *)originator;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pWOriginator->aim_target) {
|
|
|
|
if (pWOriginator->aim_target->IsSubclassOfSentient()) {
|
|
|
|
if (((Sentient *)(pWOriginator->aim_target.Pointer()))->m_Team != pAOwner->m_Team) {
|
2023-10-11 22:49:06 +02:00
|
|
|
pEnemy = (Sentient *)(pWOriginator->aim_target.Pointer());
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else if (pAOwner->m_Team == TEAM_GERMAN) {
|
|
|
|
for (pEnemy = level.m_HeadSentient[1];; pEnemy = pEnemy->m_NextSentient) {
|
|
|
|
if (!pEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Vector vDist = pEnemy->centroid - pWOriginator->aim_target->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDist.lengthSquared() <= 2304 || vDist.lengthSquared() != 2304) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!pEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!pEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//v14 = &this->m_PotentialEnemies;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_PotentialEnemies.CaresAboutPerfectInfo(pEnemy)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float fDist = sqrt(fDistSquared);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (NoticeShot(pOwner, pEnemy, fDist)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::FootstepSound(vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (originator->IsSubclassOfSentient()) {
|
|
|
|
if ((m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_IDLE
|
|
|
|
|| m_ThinkStates[THINKLEVEL_NORMAL] == THINKSTATE_CURIOUS)
|
|
|
|
&& m_bEnableEnemy) {
|
|
|
|
if (NoticeFootstep((Sentient *)originator)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
CuriousSound(AI_EVENT_FOOTSTEP, sound_origin, fDistSquared, fMaxDistSquared);
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::VoiceSound(int iType, vec3_t sound_origin, float fDistSquared, float fMaxDistSquared, Entity *originator)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
bool bFriendly;
|
|
|
|
//FIXME: macros
|
2023-10-12 18:19:22 +02:00
|
|
|
if ((m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_IDLE && m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_CURIOUS)
|
|
|
|
|| !m_bEnableEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
bFriendly = m_Team == TEAM_GERMAN;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (iType <= AI_EVENT_GERMAN_VOICE) {
|
2023-10-11 22:49:06 +02:00
|
|
|
assert(iType == AI_EVENT_AMERICAN_VOICE);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
assert(iType <= AI_EVENT_GERMAN_URGENT);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (iType == AI_EVENT_AMERICAN_URGENT) {
|
2023-10-11 22:49:06 +02:00
|
|
|
bFriendly = m_Team == TEAM_AMERICAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (bFriendly) {
|
|
|
|
if (NoticeVoice((Sentient *)originator)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
CuriousSound(iType, sound_origin, 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::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-12 18:19:22 +02:00
|
|
|
void Actor::GrenadeNotification(Entity *originator)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!m_pGrenade) {
|
|
|
|
if (CanSeeFOV(originator)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pGrenade == originator) {
|
|
|
|
float fGrav, fDeltaZ, fVelDivGrav, fTimeLand;
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (VectorLength2D(vMove) > 16) {
|
|
|
|
m_vGrenadePos = Vector(vLand[0], vLand[1], origin[2]);
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bGrenadeBounced = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::UpdateBadPlaces
|
|
|
|
|
|
|
|
Update bad places, with a new path
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::UpdateBadPlaces(void)
|
|
|
|
{
|
|
|
|
m_iBadPlaceIndex = 0;
|
|
|
|
if (!m_bIgnoreBadPlace) {
|
|
|
|
if (PathExists()) {
|
|
|
|
m_Path.ReFindPath(origin, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_iBadPlaceIndex = level.GetNearestBadPlace(origin, 64, 1 << m_Team);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::NotifySquadmateKilled(Sentient *pSquadMate, Sentient *pAttacker)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_PotentialEnemies.CaresAboutPerfectInfo(pAttacker)) {
|
|
|
|
Vector dist = pSquadMate->origin - origin;
|
|
|
|
float distSq = dist * dist;
|
|
|
|
if (distSq < m_fSight * m_fSight) {
|
2023-10-11 22:49:06 +02:00
|
|
|
bool shouldConfirm = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (gi.AreasConnected(edict->r.areanum, pSquadMate->edict->r.areanum)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
shouldConfirm = G_SightTrace(
|
|
|
|
EyePosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
pSquadMate->EyePosition(),
|
|
|
|
this,
|
|
|
|
pSquadMate,
|
|
|
|
MASK_TRANSITION,
|
|
|
|
qfalse,
|
2023-10-12 18:19:22 +02:00
|
|
|
"Actor::NotifySquadmateKilled"
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
//FIXME: macro for that constant
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!shouldConfirm) {
|
|
|
|
if (distSq <= Square(768)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector start, end;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (origin.z <= pSquadMate->origin.z) {
|
2023-10-11 22:49:06 +02:00
|
|
|
start = origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
end = pSquadMate->origin;
|
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
start = pSquadMate->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
end = origin;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
shouldConfirm = m_Path.DoesTheoreticPathExist(start, end, this, 1536, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (shouldConfirm) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::RaiseAlertnessForEventType(int iType)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float fAmount;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
switch (iType) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Team == TEAM_AMERICAN) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
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:
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Team == TEAM_AMERICAN) {
|
2023-10-11 22:49:06 +02:00
|
|
|
RaiseAlertness(0.25);
|
|
|
|
}
|
|
|
|
default:
|
2023-10-12 18:19:22 +02:00
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
fMaxAmount = m_fNoticeTimeScale * 2 / 3;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
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-12 18:19:22 +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");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pShooter->m_Team != m_Team) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bEnemyIsDisguised = false;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pTarget) {
|
|
|
|
if (DoesTheoreticPathExist(pShooter->origin, fDist * 1.5)
|
|
|
|
|| CanSee(pTarget, 0, 0.828 * world->farplane_distance, false)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_PotentialEnemies.ConfirmEnemy(this, pTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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::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-12 18:19:22 +02:00
|
|
|
bool Actor::NoticeFootstep(Sentient *pPedestrian)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Team == pPedestrian->m_Team || pPedestrian->m_bIsDisguised) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::NoticeVoice(Sentient *pVocallist)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (IsSquadMate(pVocallist)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::ValidGrenadePath(const Vector& vFrom, const Vector& vTo, Vector& vVel)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macros
|
2023-10-12 18:19:22 +02:00
|
|
|
float fGravity, fTime1, fTime2, fTime3, fTimeLand;
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector mins(-4, -4, -4);
|
|
|
|
Vector maxs(4, 4, 4);
|
|
|
|
|
|
|
|
Vector vPoint1, vPoint2, vPoint3;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vVel.lengthSquared() > 589824) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ai_debug_grenades->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
G_DebugLine(vFrom, vPoint1, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (G_SightTrace(
|
|
|
|
vFrom,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint1,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 1"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (ai_debug_grenades->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
G_DebugLine(vPoint1, vPoint2, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (G_SightTrace(
|
|
|
|
vPoint1,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint2,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 2"
|
|
|
|
)) {
|
|
|
|
if (fabs(vVel.y) >= fabs(vVel.x)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fTimeLand = (vTo.y - vFrom.y) / vVel.y;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
vPoint3.z = (vVel.z - fGravity * 0.5 * fTime3) * fTime3 + vFrom.z;
|
|
|
|
|
|
|
|
if (ai_debug_grenades->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
G_DebugLine(vPoint2, vPoint3, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (G_SightTrace(
|
|
|
|
vPoint2,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vPoint3,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107569409,
|
|
|
|
qfalse,
|
|
|
|
"Actor::ValidGrenadePath 3"
|
|
|
|
)) {
|
|
|
|
if (ai_debug_grenades->integer) {
|
2023-10-11 22:49:06 +02:00
|
|
|
G_DebugLine(vPoint3, vTo, 1.0, 0.5, 0.5, 1.0);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
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()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Sentient *sen = (Sentient *)trace.ent->entity;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (sen->m_Team != m_Team) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (trace.entityNum == 1022 && trace.plane.normal[2] >= 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::CalcThrowVelocity(const Vector& vFrom, const Vector& vTo)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector ret;
|
|
|
|
Vector vDelta;
|
2023-10-12 18:19:22 +02:00
|
|
|
float v10; // ST0C_4
|
|
|
|
float v11; // fst3
|
2023-10-11 22:49:06 +02:00
|
|
|
//////
|
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::CanThrowGrenade(const Vector& vFrom, const Vector& vTo)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vVel = vec_zero;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vVel = CalcThrowVelocity(vFrom, vTo);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return vec_zero;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::CalcRollVelocity(const Vector& vFrom, const Vector& vTo)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fOOTime, fVelVert, fVelHorz, fGravity;
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDelta.z > 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::CanRollGrenade(const Vector& vFrom, const Vector& vTo)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vVel = vec_zero;
|
2023-10-12 18:19:22 +02:00
|
|
|
vVel = CalcRollVelocity(vFrom, vTo);
|
|
|
|
if (vVel == vec_zero || !ValidGrenadePath(vFrom, vTo, vVel)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return vec_zero;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::CanTossGrenadeThroughHint(
|
|
|
|
GrenadeHint *pHint, const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode
|
|
|
|
)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float fGravity = 0.8 * sv_gravity->value;
|
2023-10-12 18:19:22 +02:00
|
|
|
float fAngle, fTemp, fTemp2, fTemp3, fTemp4, /*fVelVert, fVelHorz,*/ fRange, fRangeSquared, fDist, fDistSquared,
|
|
|
|
fHeight;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (!bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vHintDelta = pHint->origin - vFrom;
|
2023-10-12 18:19:22 +02:00
|
|
|
vDelta = vFrom - vTo;
|
|
|
|
|
|
|
|
fDist = vDelta.lengthXY();
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (fRange == 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fTemp4 = 1 / fRange;
|
|
|
|
fRange = (fDist - vHintDelta.lengthXY()) / fRange;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fRange <= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
fTemp = sqrt(fRange * (fDist * (fGravity * 0.5 * vHintDelta.lengthXY())));
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
fRange = vHintDelta.lengthXY();
|
2023-10-11 22:49:06 +02:00
|
|
|
fRangeSquared = fRange * fRange;
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fRangeSquared != 0) {
|
|
|
|
fDist = vHintDelta.length();
|
2023-10-11 22:49:06 +02:00
|
|
|
fHeight = fRangeSquared * fGravity / 589824.0 + vHintDelta.z;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (-fHeight <= -fDist) {
|
|
|
|
fAngle = (atan2(vHintDelta.z / fRangeSquared, 1.0)
|
|
|
|
+ atan2(fHeight / fDist, sqrt(1.0 - fHeight / fDist * (fHeight / fDist))))
|
|
|
|
/ 2;
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::GrenadeThrowPoint(const Vector& vFrom, const Vector& vDelta, const_str csAnim)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
vec2_t axis;
|
|
|
|
Vector vRet;
|
|
|
|
|
|
|
|
VectorCopy2D(vDelta, axis);
|
|
|
|
VectorNormalize2D(axis);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (csAnim == STRING_ANIM_GRENADEKICK_SCR) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 8;
|
|
|
|
return vRet;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (csAnim > STRING_ANIM_GRENADEKICK_SCR) {
|
|
|
|
if (csAnim != STRING_ANIM_GRENADETHROW_SCR && csAnim != STRING_ANIM_GRENADETOSS_SCR) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 80;
|
|
|
|
return vRet;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (csAnim != STRING_ANIM_GRENADERETURN_SCR) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = vFrom;
|
|
|
|
vRet.z += 80;
|
|
|
|
return vRet;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::CalcKickVelocity(Vector& vDelta, float fDist) const
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fScale, fGravity;
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector ret;
|
2023-10-12 18:19:22 +02:00
|
|
|
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;
|
2023-10-12 18:19:22 +02:00
|
|
|
v4 = sqrt(fGravity * 0.5 / (fScale - vDelta[2]));
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::CanKickGrenade(Vector& vFrom, Vector& vTo, Vector& vFace, Vector *pvVel)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vEnd, vStart, vDelta, vVel;
|
2023-10-12 18:19:22 +02:00
|
|
|
float fDist, fGravity, fScale;
|
2023-10-11 22:49:06 +02:00
|
|
|
fGravity = sv_gravity->value * 0.8;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fGravity <= 0.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDelta.z >= 0 || Vector::Dot(vDelta, vFace) < 0.0 || fDist < 256 || fDist >= 255401.28 / fGravity + 192.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-09-05 16:55:10 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDist < 512) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fScale = 192.0 / fDist + 0.25;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
fScale = 1.0 - 192.0 / fDist;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
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
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (*pvVel == vec_zero || !ValidGrenadePath(vStart, vEnd, *pvVel)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::GrenadeWillHurtTeamAt(const Vector& vTo)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pNextSquadMate == this) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-08-13 03:12:07 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (Actor *pSquadMate = (Actor *)m_pNextSquadMate.Pointer(); pSquadMate != this;
|
|
|
|
pSquadMate = (Actor *)pSquadMate->m_pNextSquadMate.Pointer()) {
|
|
|
|
if ((pSquadMate->origin - vTo).length() <= 65536) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::CanGetGrenadeFromAToB(
|
|
|
|
const Vector& vFrom, const Vector& vTo, bool bDesperate, Vector *pvVel, eGrenadeTossMode *peMode
|
|
|
|
)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fDot;
|
|
|
|
Vector vHint;
|
|
|
|
Vector vStart;
|
|
|
|
Vector vAxisY;
|
|
|
|
Vector vAxisX;
|
|
|
|
Vector vDelta;
|
|
|
|
Vector vDelta2 = vec_zero;
|
|
|
|
int nHints;
|
2023-10-11 22:49:06 +02:00
|
|
|
GrenadeHint *apHint[4];
|
2023-10-12 18:19:22 +02:00
|
|
|
float fRangeSquared;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (sv_gravity->value <= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
vDelta = vTo - vFrom;
|
2023-10-11 22:49:06 +02:00
|
|
|
fRangeSquared = vDelta.lengthSquared();
|
|
|
|
|
|
|
|
//range < 256
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fRangeSquared < Square(256)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
if (bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADERETURN_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
//range < 32
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fRangeSquared < Square(1024)) {
|
|
|
|
if (!bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pvVel = CanRollGrenade(vStart, vTo);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (*pvVel != vec_zero) {
|
2023-10-11 22:49:06 +02:00
|
|
|
*peMode = AI_GREN_TOSS_ROLL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pvVel = CanThrowGrenade(vStart, vTo);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (*pvVel != vec_zero) {
|
2023-10-11 22:49:06 +02:00
|
|
|
*peMode = AI_GREN_TOSS_THROW;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nHints = GrenadeHint::GetClosestSet(apHint, 4, vStart, Square(1024));
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = 0; i <= nHints; i++) {
|
|
|
|
if (bDesperate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADERETURN_SCR);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
vHint = apHint[i]->origin;
|
2023-10-11 22:49:06 +02:00
|
|
|
vDelta2 = vHint - vFrom;
|
|
|
|
|
|
|
|
fDot = DotProduct2D(vDelta2, vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDot >= 0 && fDot * fDot <= vDelta.lengthXYSquared() * vDelta2.lengthXYSquared() * 0.89999998) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vStart = GrenadeThrowPoint(vFrom, vDelta2, STRING_ANIM_GRENADETOSS_SCR);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (CanTossGrenadeThroughHint(apHint[i], vStart, vTo, bDesperate, pvVel, peMode)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
return true;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*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-12 18:19:22 +02:00
|
|
|
bool Actor::DecideToThrowGrenade(const Vector& vTo, Vector *pvVel, eGrenadeTossMode *peMode)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Sentient::AmmoCount("grenade")) {
|
|
|
|
if (!GrenadeWillHurtTeamAt(vTo)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
void Actor::GenericGrenadeTossThink(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector vGrenadeVel = vec_zero;
|
2023-10-11 22:49:06 +02:00
|
|
|
eGrenadeTossMode eGrenadeMode;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy && level.inttime >= m_iStateTime + 200) {
|
|
|
|
if (CanGetGrenadeFromAToB(origin, m_Enemy->velocity - m_Enemy->origin, false, &vGrenadeVel, &eGrenadeMode)) {
|
|
|
|
m_vGrenadeVel = vGrenadeVel;
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
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");
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (m_eGrenadeMode == AI_GREN_TOSS_ROLL) {
|
2023-10-11 22:49:06 +02:00
|
|
|
csAnim = STRING_ANIM_GRENADETHROW_SCR;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (m_Team == TEAM_AMERICAN) {
|
2023-10-11 22:49:06 +02:00
|
|
|
strGrenade = "models/projectiles/M2FGrenade.tik";
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetTurret(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
Listener *l = ev->GetListener(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (l && l->inheritsFrom(&TurretGun::ClassInfo)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pTurret = (TurretGun *)l;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetTurret(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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventInterruptPoint(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[m_ThinkLevel]];
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (func->PostShoot) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->PostShoot)();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventGetVisibilityThreshold(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fVisibilityThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetVisibilityThreshold(Event *ev)
|
|
|
|
{
|
|
|
|
float threshold;
|
|
|
|
|
|
|
|
threshold = ev->GetFloat(1);
|
|
|
|
|
|
|
|
if (threshold < 0 || threshold > 1) {
|
|
|
|
ScriptError("DefaultNonVisLevel must be in range 0-1");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bHasVisibilityThreshold = true;
|
|
|
|
m_fVisibilityThreshold = threshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetDefaultVisibilityThreshold(Event *ev)
|
|
|
|
{
|
|
|
|
float threshold;
|
|
|
|
|
|
|
|
threshold = ev->GetFloat(1);
|
|
|
|
|
|
|
|
if (threshold < 0 || threshold > 1) {
|
|
|
|
ScriptError("DefaultNonVisLevel must be in range 0-1");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_bHasVisibilityThreshold) {
|
|
|
|
m_fVisibilityThreshold = threshold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetSuppressChance(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddInteger(m_iSuppressChance);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventSetSuppressChance(Event *ev)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventAnimScript(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventAnimScript_Scripted(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventAnimScript_Noclip(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_csAnimScript = ev->GetConstString(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro
|
|
|
|
m_AnimMode = 6;
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetThinkIdle(THINK_ANIM);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventAnimScript_Attached(Event *ev)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventReload_mg42(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macos/enum
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_State != 1201) {
|
|
|
|
if (m_State == 1200) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAnimScriptSet = true;
|
|
|
|
TransitionState(1201, 0);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unregister(STRING_ANIMDONE);
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (PathExists()) {
|
|
|
|
delta[0] = origin[0] - m_vHome[0];
|
|
|
|
delta[1] = origin[1] - m_vHome[1];
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
return (VectorLength2DSquared(delta) < m_fLeashSquared) || (DotProduct2D(delta, m_Path.CurrentDelta()) < 0.0f);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::MovePathWithLeash(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (CanMovePathWithLeash()) {
|
|
|
|
Anim_RunToInOpen(2);
|
2023-10-11 22:49:06 +02:00
|
|
|
FaceMotion();
|
|
|
|
return true;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Anim_Aim();
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::GunTarget(bool bNoCollision)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float accuracy;
|
|
|
|
static bool doInit = true;
|
2023-10-11 22:49:06 +02:00
|
|
|
static cvar_t *aiRanges[4];
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector vRet;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (doInit) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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);
|
2023-10-12 18:19:22 +02:00
|
|
|
doInit = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (mTargetPos == vec_zero) {
|
2023-10-11 22:49:06 +02:00
|
|
|
AnglesToAxis(origin, orientation);
|
|
|
|
vRet = Vector(orientation[0]) * 2048 + EyePosition();
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
float scatterMult = 1;
|
|
|
|
|
|
|
|
Player *player = NULL;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
|
|
|
if (m_Enemy->IsSubclassOfPlayer()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
player = (Player *)m_Enemy.Pointer();
|
|
|
|
|
|
|
|
Weapon *weap = GetActiveWeapon(WEAPON_MAIN);
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector dir;
|
2023-10-11 22:49:06 +02:00
|
|
|
dir = player->centroid - centroid;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weap) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MPrintf("WEAPON RANGE: %f dist: %f\n", aiRanges[weap->mAIRange]->value, dir.length());
|
|
|
|
scatterMult = dir.length() / aiRanges[weap->mAIRange]->value;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (dir.length() > aiRanges[weap->mAIRange]->value) {
|
|
|
|
if (scatterMult > 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
accuracy = mAccuracy / scatterMult;
|
|
|
|
}
|
|
|
|
MPrintf("OUT OF RANGE - scatterMult: %f\n", scatterMult);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
strcpy(assertStr, "\"ERROR Actor::GunTarget without a weapon\\n\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (fabs(m_Enemy->origin[2] - origin[2]) >= 128) {
|
2023-10-11 22:49:06 +02:00
|
|
|
scatterMult = 0.5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (random2() > accuracy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
MPrintf("MISS - scatterMult: %f\n", scatterMult);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (player) {
|
2023-10-11 22:49:06 +02:00
|
|
|
static cvar_t *scatterHeight;
|
|
|
|
static cvar_t *scatterWide;
|
2023-10-12 18:19:22 +02:00
|
|
|
static bool doInitScatters = false;
|
|
|
|
int lastTrail;
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
lastTrail = player->mCurTrailOrigin - 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (lastTrail < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
lastTrail = 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = player->mvTrail[lastTrail];
|
|
|
|
//continue here:
|
|
|
|
//Player *tPlayer = player + 12*lastTrail;//weird
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!G_SightTrace(
|
|
|
|
GunPosition(),
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
player->mvTrail[lastTrail],
|
|
|
|
this,
|
|
|
|
player,
|
|
|
|
33819417,
|
|
|
|
0,
|
|
|
|
"Actor::GunTarget 1"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = player->mvTrailEyes[lastTrail];
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!doInitScatters) {
|
|
|
|
scatterWide = gi.Cvar_Get("g_aiScatterWide", "16.0", 0);
|
|
|
|
scatterHeight = gi.Cvar_Get("g_aiScatterHeight", "45.0", 0);
|
2023-10-11 22:49:06 +02:00
|
|
|
doInitScatters = true;
|
|
|
|
}
|
|
|
|
vRet.x += crandom() * scatterWide->value * scatterMult;
|
|
|
|
vRet.y += crandom() * scatterWide->value * scatterMult;
|
|
|
|
vRet.z += crandom() * scatterHeight->value * scatterMult;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
|
|
|
if (player && player->GetVehicleTank()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
int sign;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (random() > 0.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = -1;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.x = sign * 32 * (random() + 1);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (random() > 0.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = -1;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.y = sign * 32 * (random() + 1);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (random() > 0.5) {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = 1;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
sign = -1;
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.z = sign * 48 * (random() + 1);
|
|
|
|
|
|
|
|
vRet += mTargetPos;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (player && player->GetVehicleTank()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
MPrintf("HIT\n");
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (player) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = player->centroid;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = mTargetPos;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
|
|
|
if (!G_SightTrace(
|
|
|
|
GunPosition(), vec_zero, vec_zero, vRet, this, m_Enemy, 33819417, qfalse, "Actor::GunTarget 1"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet = EyePosition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (player && player->GetVehicleTank()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vRet.z -= 128;
|
|
|
|
}
|
|
|
|
return vRet;
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
qboolean Actor::setModel(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
str headModel, headSkin, weapon;
|
|
|
|
headModel = level.GetRandomHeadModel(model);
|
2023-10-12 18:19:22 +02:00
|
|
|
headSkin = level.GetRandomHeadSkin(model);
|
2023-10-11 22:49:06 +02:00
|
|
|
//qboolean bSuccess;
|
|
|
|
str name = "", tempstr;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (model != "") {
|
|
|
|
if (m_csLoadOut != STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
name = "weapon|" + Director.GetString(m_csLoadOut) + "|";
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csHeadModel == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csHeadModel = Director.AddString(level.GetRandomHeadModel(model));
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csHeadModel != STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
name += "headmodel|" + Director.GetString(m_csHeadModel) + "|";
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csHeadSkin == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_csHeadSkin = Director.AddString(level.GetRandomHeadSkin(model));
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csHeadSkin != STRING_EMPTY) {
|
|
|
|
name += "headskin|" + Director.GetString(m_csHeadSkin) + "|"; //FIXME: not sure of this last "|"
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
name += model;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
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()
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
level.skel_index[edict->s.number] = -1;
|
|
|
|
return gi.setmodel(edict, name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::SetPathWithLeash(Vector vDestPos, const char *description, int iMaxDirtyTime)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
vec2_t dist = {vDestPos[0] - m_vHome[0], vDestPos[1] - m_vHome[1]};
|
|
|
|
float distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dist[0] = origin[0] - m_vHome[0];
|
|
|
|
dist[1] = origin[1] - m_vHome[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared) {
|
|
|
|
SetPath(vDestPos, description, iMaxDirtyTime, m_vHome, m_fLeashSquared);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPath();
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::SetPathWithLeash(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pDestNode) {
|
|
|
|
SetPathWithLeash(pDestNode->origin, description, iMaxDirtyTime);
|
|
|
|
} else {
|
|
|
|
if (m_bPathErrorTime + 5000 < level.inttime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bPathErrorTime = level.inttime;
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ No destination node specified for '%s' at (%f %f %f)\n",
|
|
|
|
targetname.c_str(),
|
|
|
|
origin[0],
|
|
|
|
origin[1],
|
2023-10-12 18:19:22 +02:00
|
|
|
origin[2]
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
ClearPath();
|
|
|
|
}
|
|
|
|
}
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::FindPathAwayWithLeash(vec3_t vAwayFrom, vec3_t vDirPreferred, float fMinSafeDist)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
m_Path.FindPathAway(origin, vAwayFrom, vDirPreferred, this, fMinSafeDist, m_vHome, m_fLeashSquared);
|
2023-10-11 22:49:06 +02:00
|
|
|
ShortenPathToAvoidSquadMates();
|
|
|
|
}
|
2018-08-29 14:41:48 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::FindPathNearWithLeash(vec3_t vNearbyTo, float fCloseDistSquared)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
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)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dist[0] = origin[0] - m_vHome[0];
|
|
|
|
dist[1] = origin[1] - m_vHome[1];
|
2023-10-12 18:19:22 +02:00
|
|
|
distSq = DotProduct2D(dist, dist);
|
|
|
|
if (distSq <= m_fLeashSquared) {
|
|
|
|
m_Path.FindPathNear(origin, vNearbyTo, this, 0, fCloseDistSquared, m_vHome, m_fLeashSquared);
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector Actor::GetAntiBunchPoint(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
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) {
|
2023-10-11 22:49:06 +02:00
|
|
|
count++;
|
2023-10-12 18:19:22 +02:00
|
|
|
ret += origin + (dist / sqrt(distSq)) * (m_fInterval - sqrt(distSq));
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (count) {
|
|
|
|
if (count != 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ret /= count;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ret = origin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (lastActor) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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()
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::ResetBodyQueue(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
//weird useless loop ?
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = MAX_BODYQUEUE - 1; i >= 0; i--) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//do nothing.
|
|
|
|
}
|
|
|
|
//mBodyQueue
|
|
|
|
//this resets curBody, but all the magic happens in AddToBodyQue
|
|
|
|
mCurBody = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetNoIdle(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetNoIdle(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetEnemy(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetMaxNoticeTimeScale(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);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (noticeScale <= 0.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Com_Printf("^~^~^ ERROR: noticescale: value must be greater than 0\n");
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxNoticeTimeScale = noticeScale / 100;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetMaxNoticeTimeScale(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetFixedLeash(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetFixedLeash(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::Holster(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (activeWeaponList[0]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
DeactivateWeapon(WEAPON_MAIN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::HolsterOffHand(void)
|
|
|
|
{
|
|
|
|
if (activeWeaponList[WEAPON_OFFHAND]) {
|
|
|
|
DeactivateWeapon(WEAPON_OFFHAND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::Unholster(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-12 19:21:41 +02:00
|
|
|
if (!activeWeaponList[WEAPON_MAIN]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
weap = GetWeapon(WEAPON_MAIN);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (weap) {
|
2023-10-11 22:49:06 +02:00
|
|
|
useWeapon(weap, WEAPON_MAIN);
|
|
|
|
ActivateNewWeapon();
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::UnholsterOffHand(void)
|
|
|
|
{
|
|
|
|
Weapon *weap;
|
|
|
|
|
|
|
|
if (!activeWeaponList[WEAPON_OFFHAND]) {
|
|
|
|
weap = GetWeapon(WEAPON_OFFHAND);
|
|
|
|
if (weap) {
|
|
|
|
useWeapon(weap, WEAPON_OFFHAND);
|
|
|
|
ActivateNewWeapon();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventHolster(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (activeWeaponList[WEAPON_MAIN]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
DeactivateWeapon(WEAPON_MAIN);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventIsEnemyVisible(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetEnemyVisibleChangeTime(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetLastEnemyVisibleTime(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: /100 ??
|
2023-10-12 18:19:22 +02:00
|
|
|
ev->AddFloat(m_iLastEnemyVisibleTime / 100);
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSoundDone(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//soundChannel_t
|
|
|
|
int channel = ev->GetInteger(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
str name = ev->GetString(2);
|
|
|
|
if (gi.S_IsSoundPlaying(channel, name)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Event e1(EV_SoundDone);
|
|
|
|
e1.AddInteger(channel);
|
|
|
|
e1.AddString(name);
|
|
|
|
PostEvent(e1, level.frametime);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_bSayAnimSet && m_iSaySlot == -2) //FIXME: macro
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ChangeSayAnim();
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_csSayAnim == STRING_EMPTY) {
|
2023-10-11 22:49:06 +02:00
|
|
|
//gi.DPrintf("unregister STRING_SAYDONE\n");
|
|
|
|
Unregister(STRING_SAYDONE);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
Unregister(STRING_SOUNDDONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetFallHeight(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-12 18:19:22 +02:00
|
|
|
if (fHeight < MIN_FALLHEIGHT) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("value less than %d not allowed", MIN_FALLHEIGHT);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fHeight > MAX_FALLHEIGHT) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetFallHeight(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventCanMoveTo(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fIntervalSquared, fDistSquared;
|
2023-10-11 22:49:06 +02:00
|
|
|
vec2_t vDelta;
|
|
|
|
Vector vDest;
|
|
|
|
|
|
|
|
vDest = ev->GetVector(1);
|
|
|
|
VectorSub2D(vDest, m_vHome, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fDistSquared >= m_fLeashSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(0);
|
|
|
|
return;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (m_Enemy != NULL) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorSub2D(vDest, m_Enemy->origin, vDelta);
|
|
|
|
fDistSquared = VectorLength2DSquared(vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMinDistanceSquared >= fDistSquared || fDistSquared >= m_fMaxDistanceSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(qfalse);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fInterval == 0) {
|
|
|
|
for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
float v27, v29, v30, v32, v33, v34, v35, v37, v38;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pSquadMate->IsSubclassOfActor()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Sentient *pEnemy = pSquadMate->m_Enemy;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pEnemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
v27 = pSquadMate->origin[0];
|
|
|
|
v29 = pEnemy->origin[0] - v27;
|
|
|
|
v30 = pSquadMate->origin[1];
|
|
|
|
v32 = pEnemy->origin[1] - v30;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
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.
|
2023-10-12 18:19:22 +02:00
|
|
|
if (((int)v38 ^ (int)v35) < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(qfalse);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev->AddInteger(qtrue);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fIntervalSquared = Square(m_fInterval);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (auto pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector vDel;
|
|
|
|
vDel = vDest - pSquadMate->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fIntervalSquared <= vDest.lengthSquared()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if ((origin - pSquadMate->origin).lengthSquared() > vDest.lengthSquared()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev->AddInteger(qfalse);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventMoveDir(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
vec2_t vec;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!PathGoalSlowdownStarted()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vec[0] = velocity.x;
|
|
|
|
vec[1] = velocity.y;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (velocity.x == 0 && velocity.y == 0 && PathExists() && !PathComplete()) {
|
|
|
|
vec[0] = PathDelta()[0];
|
|
|
|
vec[1] = PathDelta()[1];
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
VectorNormalize2D(vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
ev->AddVector(vec);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventIntervalDir(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macro
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime >= m_iIntervalDirTime + 250) {
|
|
|
|
m_vIntervalDir = vec_zero;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_iIntervalDirTime = level.inttime;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_vIntervalDir = GetAntiBunchPoint() - origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_vIntervalDir.x != 0 || m_vIntervalDir.y != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorNormalizeFast(m_vIntervalDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddVector(m_vIntervalDir);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventResetLeash(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventTether(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_pTetherEnt = ev->GetSimpleEntity(1);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::ShortenPathToAttack(float fMinDist)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) {
|
|
|
|
for (auto current_node = CurrentPathNode(); current_node >= LastPathNode(); current_node--) {
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector dist = current_node->point - origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (dist * dist >= fMinDist * fMinDist) {
|
|
|
|
if (CanSeeFrom(eyeposition + current_node->point, m_Enemy)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_Path.TrimPathFromEnd((current_node - LastPathNode()) / 32);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::StrafeToAttack(float fDist, vec3_t vDir)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vEnemyCentroid, vDelta, vSpot, vDestPos;
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector mins(-16, -16, 16);
|
|
|
|
Vector maxs(16, 16, 128);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
vDestPos = vDir;
|
|
|
|
vDestPos *= fDist;
|
|
|
|
vDestPos += origin;
|
|
|
|
|
|
|
|
vDelta = vDestPos - m_vLastEnemyPos;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_fMaxDistanceSquared <= vDelta.lengthSquared() || vDelta.lengthSquared() <= m_fMinDistanceSquared) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPath();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!G_SightTrace(
|
2023-10-12 18:19:22 +02:00
|
|
|
origin,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vDestPos,
|
|
|
|
this,
|
|
|
|
NULL,
|
|
|
|
//FIXME: macro
|
|
|
|
1107437825,
|
|
|
|
qtrue,
|
|
|
|
"Actor::StrafeToAttack 1"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPath();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vSpot = vDir;
|
|
|
|
vSpot *= fDist;
|
|
|
|
|
|
|
|
vDelta = m_vLastEnemyPos;
|
|
|
|
vDelta.z += m_Enemy->centroid.z - m_Enemy->origin.z;
|
|
|
|
|
|
|
|
if (!G_SightTrace(
|
2023-10-12 18:19:22 +02:00
|
|
|
EyePosition() + vSpot,
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
vDelta,
|
|
|
|
this,
|
|
|
|
m_Enemy,
|
|
|
|
//FIXME: macro
|
|
|
|
33819417,
|
|
|
|
qfalse,
|
|
|
|
"Actor::StrafeToAttack 1"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetPathWithLeash(vDestPos, NULL, 0);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ClearPath();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetThinkState(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetEnemyShareRange(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetEnemyShareRange(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float fRange = ev->GetFloat(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMaxShareDistSquared = fRange * fRange;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::GetVoiceType(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//voice type in actor is a char.
|
2023-10-12 18:19:22 +02:00
|
|
|
const char *vType = va("%c", mVoiceType);
|
|
|
|
str vTypeStr = vType;
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddString(vTypeStr);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::SetVoiceType(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//voice type in actor is a char.
|
|
|
|
str vType = ev->GetString(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vType[0]) {
|
2023-10-11 22:49:06 +02:00
|
|
|
mVoiceType = vType[0];
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: enum
|
|
|
|
mVoiceType = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
PathNode *Actor::FindSniperNodeAndSetPath(bool *pbTryAgain)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
PathNode *pSniperNode = PathManager.FindNearestSniperNode(this, origin, m_Enemy);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pSniperNode) {
|
|
|
|
SetPathWithLeash(pSniperNode, NULL, 0);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (PathExists() && (PathComplete() || PathAvoidsSquadMates())) {
|
2023-10-11 22:49:06 +02:00
|
|
|
*pbTryAgain = true;
|
|
|
|
return pSniperNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
pSniperNode->MarkTemporarilyBad();
|
|
|
|
*pbTryAgain = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
*pbTryAgain = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::Remove(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
EndStates();
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (deadflag != DEAD_DEAD) {
|
|
|
|
health = 0;
|
2023-10-11 22:49:06 +02:00
|
|
|
deadflag = DEAD_DEAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
Delete();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetKickDir(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetNoLongPain(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetNoLongPain(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-12 18:19:22 +02:00
|
|
|
void Actor::DontFaceWall(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//PathNode *pNode;
|
2023-10-12 18:19:22 +02:00
|
|
|
vec2_t vDelta;
|
2023-10-11 22:49:06 +02:00
|
|
|
float /*fErrorLerp,*/ fEyeRadius, fCosAngle, fSinAngle, fAngle, fAngleRad, fTime;
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector start;
|
|
|
|
Vector end;
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
//FIXME: macro: AI_*
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_pCoverNode && m_pCoverNode->nodeflags & (AI_CORNER_LEFT | AI_CORNER_RIGHT | AI_SNIPER | AI_CRATE)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (velocity.lengthXYSquared() > Square(8)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fAngle = AngleNormalize360(m_YawAchieved ? angles.y : m_DesiredYaw);
|
|
|
|
|
|
|
|
fTime = (level.time - m_fDfwTime) * 0.5;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (fTime > 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fTime = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorSub2D(m_vDfwPos, origin, vDelta);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (Square(fTime * -14.0 + 16.0) > VectorLength2DSquared(vDelta)
|
2023-10-11 22:49:06 +02:00
|
|
|
&& (fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0
|
2023-10-12 18:19:22 +02:00
|
|
|
|| fabs(AngleNormalize180(m_fDfwDerivedYaw - m_DesiredYaw)) <= fTime * -29.0 + 30.0)) {
|
|
|
|
if (m_eDontFaceWallMode <= 8) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYaw(m_fDfwDerivedYaw);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
m_vDfwPos = origin;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fDfwRequestedYaw = fAngle;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_fDfwTime = level.time;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
|
|
|
fAngleRad = fAngle * M_PI / 180;
|
|
|
|
fSinAngle = sin(fAngleRad);
|
|
|
|
fCosAngle = cos(fAngleRad);
|
|
|
|
|
|
|
|
VectorSub2D(EyePosition(), origin, vDelta);
|
|
|
|
fEyeRadius = VectorLength2D(vDelta);
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
start = vec_zero;
|
2023-10-11 22:49:06 +02:00
|
|
|
start.x = fEyeRadius * fCosAngle + origin.x;
|
|
|
|
start.y = fEyeRadius * fSinAngle + origin.y;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
end = vec_zero;
|
|
|
|
end.x = 64 * fCosAngle + start.x;
|
|
|
|
end.x = 64 * fSinAngle + start.y;
|
2023-10-11 22:49:06 +02:00
|
|
|
trace_t trace = G_Trace(start, vec_zero, vec_zero, end, this, 33819417, qfalse, "Actor::DontFaceWall");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (trace.entityNum == 1023 || trace.fraction >= 1 || trace.startsolid) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 3;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (trace.entityNum == 1022 || trace.ent->entity->AIDontFace()) {
|
|
|
|
if (trace.plane.normal[2] < -0.69999999 || trace.plane.normal[2] > 0.69999999) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 5;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (m_Enemy && Vector::Dot(trace.plane.normal, m_Enemy->origin) - trace.plane.dist < 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
end = m_Enemy->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
end = start + (end - start) * 128;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PathNode *node = PathManager.FindCornerNodeForWall(origin, end, this, 0.0f, trace.plane.normal);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (node) {
|
2023-10-11 22:49:06 +02:00
|
|
|
VectorSub2D(node->m_PathPos, origin, vDelta);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDelta[0] != 0 || vDelta[1] != 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYawDir(vDelta);
|
|
|
|
}
|
|
|
|
m_eDontFaceWallMode = 6;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else if (trace.fraction <= 0.46875) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYawDir(trace.plane.normal);
|
|
|
|
m_eDontFaceWallMode = 7;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (m_DesiredYaw < 90.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_DesiredYaw += 270.0;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
m_DesiredYaw -= 90.0;
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
m_YawAchieved = false;
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 8;
|
|
|
|
}
|
|
|
|
m_fDfwDerivedYaw = m_DesiredYaw;
|
|
|
|
return;
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_eDontFaceWallMode = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fDfwDerivedYaw = m_fDfwRequestedYaw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
bool Actor::IsIdleState(int state)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
return state == THINKSTATE_IDLE;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 19:21:41 +02:00
|
|
|
bool Actor::IsBadPlaceState(int state)
|
|
|
|
{
|
|
|
|
return state == THINKSTATE_BADPLACE;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::InitVoid(GlobalFuncs_t *func)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
func->IsState = &Actor::IsVoidState;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::BecomeCorpse(void)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetFavoriteEnemy(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddEntity(m_FavoriteEnemy);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetFavoriteEnemy(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
Sentient *fEnemy = (Sentient *)ev->GetEntity(1);
|
|
|
|
m_FavoriteEnemy = fEnemy;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventFindEnemy(Event *ev)
|
|
|
|
{
|
|
|
|
if (level.inttime > m_iEnemyCheckTime + 200) {
|
|
|
|
UpdateEnemyInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
ev->AddEntity(m_Enemy);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetMumble(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddInteger(m_bMumble);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetMumble(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_bMumble = ev->GetInteger(1);
|
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventCalcGrenadeToss2(Event *ev)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventCalcGrenadeToss(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
//FIXME: macros
|
|
|
|
Vector vTarget;
|
|
|
|
vTarget = ev->GetVector(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (DecideToThrowGrenade(vTarget, &m_vGrenadeVel, &m_eGrenadeMode)) {
|
|
|
|
if (m_eGrenadeMode == AI_GREN_TOSS_ROLL) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
if (m_eGrenadeMode > AI_GREN_TOSS_ROLL ? m_eGrenadeMode == AI_GREN_TOSS_HINT
|
|
|
|
: m_eGrenadeMode == AI_GREN_TOSS_THROW) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(STRING_ANIM_GRENADETHROW_SCR);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
|
|
|
char assertStr[16317] = {0};
|
2023-10-11 22:49:06 +02:00
|
|
|
strcpy(assertStr, "\"invalid return condition for Actor::EventCalcGrenadeToss\"\n\tMessage: ");
|
|
|
|
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace(""));
|
|
|
|
assert(false && assertStr);
|
|
|
|
}
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredYawDir(m_vGrenadeVel);
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddConstString(STRING_EMPTY);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetNoSurprise(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetNoSurprise(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bNoSurprise = ev->GetBoolean(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetSilent(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetSilent(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetAvoidPlayer(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetAvoidPlayer(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bAutoAvoidPlayer = ev->GetBoolean(1);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::PathnodeClaimRevoked(PathNode *node)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
for (int i = m_ThinkLevel; i >= 0; --i) {
|
2023-10-11 22:49:06 +02:00
|
|
|
GlobalFuncs_t *func = &GlobalFuncs[m_Think[i]];
|
2023-10-12 18:19:22 +02:00
|
|
|
if (func->PathnodeClaimRevoked) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(this->*func->PathnodeClaimRevoked)();
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
node->Relinquish();
|
|
|
|
m_pCoverNode = NULL;
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::SetPathToNotBlockSentient(Sentient *pOther)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vDest, vPerp, vAway;
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pOther) {
|
|
|
|
if (!pOther->IsDead()) {
|
|
|
|
if (IsTeamMate(pOther)) {
|
|
|
|
if (pOther->velocity.lengthSquared() > 1) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vDest = origin - pOther->origin;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (vDest.lengthSquared() < 2304 && DotProduct2D(pOther->velocity, vDest) > 0) {
|
|
|
|
if (CrossProduct2D(vDest, pOther->velocity) >= 0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vPerp.x = -pOther->velocity.y;
|
|
|
|
vPerp.y = pOther->velocity.x;
|
|
|
|
vPerp.z = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
vPerp.x = pOther->velocity.y;
|
|
|
|
vPerp.y = -pOther->velocity.x;
|
|
|
|
vPerp.z = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorNormalizeFast(vPerp);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
vAway = vPerp * 48 + origin;
|
|
|
|
|
|
|
|
if (G_SightTrace(
|
|
|
|
vAway,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vAway,
|
|
|
|
this,
|
|
|
|
pOther,
|
|
|
|
33557249,
|
|
|
|
0,
|
2023-10-12 18:19:22 +02:00
|
|
|
"Actor::SetPathToNotBlockSentient 1"
|
|
|
|
)) {
|
|
|
|
SetPathWithinDistance(vAway, NULL, 96, 0);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!PathExists()) {
|
|
|
|
vAway = vDest;
|
|
|
|
VectorNormalizeFast(vAway);
|
|
|
|
|
|
|
|
vAway = vAway * 48 + origin;
|
|
|
|
if (G_SightTrace(
|
2023-10-11 22:49:06 +02:00
|
|
|
vAway,
|
|
|
|
mins,
|
|
|
|
maxs,
|
|
|
|
vAway,
|
|
|
|
this,
|
|
|
|
pOther,
|
|
|
|
33557249,
|
|
|
|
0,
|
2023-10-12 18:19:22 +02:00
|
|
|
"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"
|
|
|
|
)) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetPathWithinDistance(vAway, NULL, 96, 0);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (!PathExists()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
vAway = vDest;
|
|
|
|
VectorNormalizeFast(vAway);
|
|
|
|
|
|
|
|
FindPathAway(origin, vAway * 100, 96);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::LookAround
|
|
|
|
|
|
|
|
Look around behaviour.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::LookAround(float fFovAdd)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
Vector vDest, vAngle;
|
2023-10-12 18:19:22 +02:00
|
|
|
float fModTime;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (level.inttime >= m_iNextLookTime) {
|
2023-10-11 22:49:06 +02:00
|
|
|
fModTime = level.time;
|
2023-10-12 18:19:22 +02:00
|
|
|
vAngle = angles;
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
vAngle.y += fFovAdd * (2 * (fModTime * 0.125 - floor(fModTime * 0.125)) - 1.0);
|
2023-10-11 22:49:06 +02:00
|
|
|
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");
|
2023-10-12 18:19:22 +02:00
|
|
|
if (trace.fraction > 0.125) {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookDest = true;
|
|
|
|
VectorCopy(trace.endpos, m_vDesiredLookDest);
|
|
|
|
m_iNextLookTime = level.inttime + rand() % 500 + 750;
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookDest = false;
|
2023-10-12 18:19:22 +02:00
|
|
|
m_iNextLookTime = level.inttime + 187;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_bHasDesiredLookDest) {
|
2023-10-11 22:49:06 +02:00
|
|
|
SetDesiredLookDir(m_vDesiredLookDest - EyePosition());
|
2023-10-12 18:19:22 +02:00
|
|
|
} else {
|
2023-10-11 22:49:06 +02:00
|
|
|
m_bHasDesiredLookAngles = false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetLookAroundAngle(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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetLookAroundAngle(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-11 22:49:06 +02:00
|
|
|
float angle = ev->GetFloat(1);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (angle < 0.0 || angle > 60.0) {
|
2023-10-11 22:49:06 +02:00
|
|
|
ScriptError("lookaroundangle must be >= 0 and <= 60");
|
|
|
|
}
|
|
|
|
m_fLookAroundFov = angle;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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
|
2023-10-12 18:19:22 +02:00
|
|
|
Vector head = GetControllerAngles(HEAD_TAG);
|
2023-10-11 22:49:06 +02:00
|
|
|
Vector torso = GetControllerAngles(TORSO_TAG);
|
2023-10-12 18:19:22 +02:00
|
|
|
MPrintf(
|
|
|
|
"Desired look yaw: %.1f, pitch: %.1f. Head yaw: %.1f, pitch %.1f. Torso yaw: %.1f, pitch: %.1f\n",
|
2023-10-11 22:49:06 +02:00
|
|
|
desiredLook.x,
|
|
|
|
desiredLook.y,
|
|
|
|
head.x,
|
|
|
|
head.y,
|
|
|
|
torso.x,
|
|
|
|
torso.y
|
2023-10-12 18:19:22 +02:00
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::DumpCallTrace
|
|
|
|
|
|
|
|
Dump useful debug info.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
const char *Actor::DumpCallTrace(const char *pszFmt, ...) const
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
cvar_t *sv_mapname;
|
2023-10-12 18:19:22 +02:00
|
|
|
tm *ptm;
|
|
|
|
time_t t;
|
|
|
|
Vector vPlayer = vec_zero;
|
|
|
|
char szFile[64];
|
|
|
|
int i2;
|
2023-10-11 22:49:06 +02:00
|
|
|
//int i1;
|
2023-10-12 18:19:22 +02:00
|
|
|
int i;
|
2023-10-11 22:49:06 +02:00
|
|
|
char szTemp[65536];
|
|
|
|
char szTemp2[1024];
|
|
|
|
|
|
|
|
va_list va;
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
va_start(va, pszFmt);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
sv_mapname = gi.Cvar_Get("mapname", "unknown", 0);
|
|
|
|
|
|
|
|
Player *p = (Player *)G_GetEntity(0);
|
2023-10-12 18:19:22 +02:00
|
|
|
if (p) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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],
|
2023-10-12 18:19:22 +02:00
|
|
|
vPlayer[2]
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
if (pszFmt) {
|
2023-10-11 22:49:06 +02:00
|
|
|
i2 = i + vsprintf(&szTemp[i], pszFmt, va);
|
|
|
|
}
|
2023-10-12 18:19:22 +02:00
|
|
|
if (i2 != i) {
|
2023-10-11 22:49:06 +02:00
|
|
|
strcpy(&szTemp[i2], "\n--------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
t = time(0);
|
2023-10-11 22:49:06 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
ptm->tm_min
|
|
|
|
);
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
for (i = 0; szFile[i]; i++) {
|
|
|
|
if (szFile[i] == '\\' || szFile[i] == '/') {
|
2023-10-11 22:49:06 +02:00
|
|
|
szFile[i] = '_';
|
2023-10-12 18:19:22 +02:00
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
|
|
|
sprintf(szTemp2, "Include '%s' in your bug report!", szFile);
|
|
|
|
//PreAssertMessage:
|
|
|
|
fprintf(stderr, "IMPORTANT: %s\n", szTemp2);
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
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,
|
2023-10-12 18:19:22 +02:00
|
|
|
szTemp
|
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetMoveDoneRadius(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
float moveDoneR = ev->GetFloat(1);
|
2023-10-11 22:49:06 +02:00
|
|
|
m_fMoveDoneRadiusSquared = Square(moveDoneR);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventGetMoveDoneRadius(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddFloat(sqrtf(m_fMoveDoneRadiusSquared));
|
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::StoppedWaitFor
|
|
|
|
|
|
|
|
Called when stopped wait for an actor.
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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-12 18:19:22 +02:00
|
|
|
if (func->FinishedAnimation) {
|
2023-10-11 22:49:06 +02:00
|
|
|
(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-12 18:19:22 +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();
|
2023-10-12 18:19:22 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
ev->AddInteger(completeLH);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventPathDist(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
float dist = 0;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (PathExists() && !PathComplete()) {
|
2023-10-11 22:49:06 +02:00
|
|
|
dist = PathDist();
|
|
|
|
}
|
|
|
|
ev->AddFloat(dist);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
if (m_Enemy) {
|
2023-10-11 22:49:06 +02:00
|
|
|
canShoot = CanSeeFrom(ev->GetVector(1), m_Enemy);
|
|
|
|
}
|
|
|
|
ev->AddInteger(canShoot);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (!target) {
|
2023-10-11 22:49:06 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetBalconyHeight(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
|
|
|
}
|
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventSetIgnoreBadPlace(Event *ev)
|
|
|
|
{
|
|
|
|
if (m_bIgnoreBadPlace != ev->GetBoolean(1)) {
|
|
|
|
m_bIgnoreBadPlace = ev->GetBoolean(1);
|
|
|
|
|
|
|
|
if (level.m_badPlaces.NumObjects() && m_bIgnoreBadPlace) {
|
|
|
|
UpdateBadPlaces();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Actor::EventGetIgnoreBadPlace(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddInteger(m_bIgnoreBadPlace);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventGetBalconyHeight(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-12 18:19:22 +02:00
|
|
|
void Actor::BecomeTurretGuy(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +02:00
|
|
|
SetThinkIdle(THINK_IDLE);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-10-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
if (CurrentThink() == THINK_IDLE && Turret_DecideToSelectState()) {
|
|
|
|
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()
|
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 18:19:22 +02:00
|
|
|
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
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::EventEnableEnemySwitch
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventEnableEnemySwitch(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
m_bEnemySwitch = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::EventDisableEnemySwitch
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventDisableEnemySwitch(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
m_bEnemySwitch = false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::EventSetRunAnimRate
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventSetRunAnimRate(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
m_fRunAnimRate = ev->GetFloat(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::EventGetRunAnimRate
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::EventGetRunAnimRate(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddFloat(m_fRunAnimRate);
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::Landed
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::Landed(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
bool Actor::IsOnFloor(void)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return false;
|
2023-10-11 22:49:06 +02:00
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::GetNationality
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::GetNationality(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
// FIXME: unimplemented
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
/*
|
|
|
|
===============
|
2023-10-12 19:21:41 +02:00
|
|
|
Actor::SetNationality
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::SetNationality(Event *ev)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
2023-10-11 22:49:06 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventWriteStats
|
2023-10-11 22:49:06 +02:00
|
|
|
===============
|
|
|
|
*/
|
2023-10-12 19:21:41 +02:00
|
|
|
void Actor::EventWriteStats(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 19:21:41 +02:00
|
|
|
if (g_aistats->integer) {
|
|
|
|
level.OpenActorStats();
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventCuriousOff
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::EventCuriousOff(Event *ev)
|
|
|
|
{
|
|
|
|
m_bIsCurious = false;
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 19:21:41 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Actor::EventCuriousOn
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Actor::EventCuriousOn(Event *ev)
|
|
|
|
{
|
|
|
|
m_bIsCurious = true;
|
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-12 18:19:22 +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-12 18:19:22 +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-12 18:19:22 +02:00
|
|
|
void Actor::EventGetBreathSteam(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
ev->AddInteger(m_bBreathSteam);
|
|
|
|
}
|
2018-08-19 08:26:59 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
void Actor::EventSetBreathSteam(Event *ev)
|
2023-10-11 22:49:06 +02:00
|
|
|
{
|
|
|
|
m_bBreathSteam = ev->GetInteger(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-10-12 18:19:22 +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;
|
2023-10-12 18:19:22 +02:00
|
|
|
ScriptThread *t = Director.CreateThread("global/breathe.scr", "nextbreathtime");
|
|
|
|
|
2023-10-11 22:49:06 +02:00
|
|
|
sVar.setFloatValue(ev->GetFloat(1));
|
|
|
|
t->Execute(&sVar, 1);
|
|
|
|
}
|
2018-08-05 17:56:40 +02:00
|
|
|
|
2023-10-12 18:19:22 +02:00
|
|
|
bool Actor::EnemyIsDisguised(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-10-12 18:19:22 +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
|
|
|
}
|
2023-10-12 19:21:41 +02:00
|
|
|
|
|
|
|
bool Actor::IsDisabled() const
|
|
|
|
{
|
|
|
|
return !m_bDoAI;
|
|
|
|
}
|