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
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// entity.cpp: Base class for all enities that are controlled by Sin. If you have any
// object that should be called on a periodic basis and it is not an entity,
// then you have to have an dummy entity that calls it.
//
// An entity in Sin is any object that is not part of the world-> Any non-world
// object that is visible in Sin is an entity, although it is not required that
// all entities be visible to the player. Some objects are basically just virtual
// constructs that act as an instigator of certain actions, for example, some
// triggers are invisible and cannot be touched, but when activated by other
// objects can cause things to happen.
//
// All entities are capable of receiving messages from Sin or from other entities.
// Messages received by an entity may be ignored, passed on to their superclass,
// or acted upon by the entity itself. The programmer must decide on the proper
// action for the entity to take to any message. There will be many messages
// that are completely irrelevant to an entity and should be ignored. Some messages
// may require certain states to exist and if they are received by an entity when
// it these states don't exist may indicate a logic error on the part of the
// programmer or map designer and should be reported as warnings (if the problem is
// not severe enough for the game to be halted) or as errors (if the problem should
// not be ignored at any cost).
//
# include "entity.h"
# include "scriptmaster.h"
# include "sentient.h"
# include "misc.h"
# include "specialfx.h"
# include "object.h"
# include "player.h"
# include "weaputils.h"
# include "soundman.h"
2023-04-29 21:56:38 +02:00
# include "scriptexception.h"
# include "qfiles.h"
2016-03-27 11:49:47 +02:00
# include "g_spawn.h"
2023-04-29 21:56:38 +02:00
# include "g_phys.h"
# include "debuglines.h"
2023-01-30 00:23:47 +01:00
# include <tiki.h>
2023-09-07 20:01:07 +02:00
# include <utility>
2016-03-27 11:49:47 +02:00
// Generic entity events
2023-08-09 23:09:09 +02:00
Event EV_SoundDone (
" saydone " , EV_DEFAULT , NULL , NULL , " Even used by sound-only special case of say to trigger waittill saydone "
) ;
2016-03-27 11:49:47 +02:00
Event EV_Classname
2023-08-09 23:09:09 +02:00
(
" classname " ,
EV_DEFAULT ,
" s " ,
" nameOfClass " ,
" Determines what class to use for this entity, \n "
" this is pre-processed from the BSP at the start \n "
" of the level. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SpawnFlags
2023-08-09 23:09:09 +02:00
(
2023-08-09 23:27:08 +02:00
" spawnflags " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
" i " ,
" flags " ,
2023-08-09 23:27:08 +02:00
" spawnflags from the BSP, "
" these are set inside the editor " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2018-09-17 23:50:38 +02:00
Event EV_GetNormalHealth
2023-08-09 23:09:09 +02:00
(
" normal_health " ,
EV_DEFAULT ,
NULL ,
NULL ,
" The Normal Health of the Actor " ,
EV_GETTER
) ;
2018-09-17 23:50:38 +02:00
Event EV_NormalDamage
(
2023-08-09 23:09:09 +02:00
" normal_damage " ,
EV_DEFAULT ,
NULL ,
NULL ,
" The Normal Health of the Actor (0 - 100) " ,
EV_NORMAL
2018-09-17 23:50:38 +02:00
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetTeam
2023-08-09 23:09:09 +02:00
(
" team " ,
EV_DEFAULT ,
" s " ,
" moveTeam " ,
" used to make multiple entities move together. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Trigger
2023-08-09 23:09:09 +02:00
(
" trigger " ,
EV_DEFAULT ,
" s " ,
" name " ,
" Trigger the specified target or entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Activate
2023-08-09 23:09:09 +02:00
(
" doActivate " ,
EV_DEFAULT ,
" e " ,
" activatingEntity " ,
" General trigger event for all entities " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Use
2023-08-09 23:09:09 +02:00
(
" doUse " ,
EV_DEFAULT ,
" e " ,
" activatingEntity " ,
" sent to entity when it is used by another entity " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_FadeNoRemove
2023-08-09 23:09:09 +02:00
(
" fade " ,
EV_DEFAULT ,
" F[0,]F[0,1] " ,
" fadetime target_alpha " ,
" Fade the entity's alpha, reducing it by 0.03 \n "
" every FRAMETIME, until it has faded out, does not remove the entity " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_FadeOut
2023-08-09 23:09:09 +02:00
(
" _fadeout " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Fade the entity's alpha and scale out, reducing it by 0.03 \n "
" every FRAMETIME, until it has faded out, removes the entity \n "
" Once the entity has been completely faded, the entity is removed. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Fade
2023-08-09 23:09:09 +02:00
(
" fadeout " ,
EV_DEFAULT ,
" F[0,]F[0,1] " ,
" fadetime target_alpha " ,
" Fade the entity's alpha and scale out, reducing it by 0.03 \n "
" every FRAMETIME, until it has faded out. If fadetime or \n "
" target_alpha are defined, they will override the defaults. \n "
" Once the entity has been completely faded, the entity is removed. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_FadeIn
2023-08-09 23:09:09 +02:00
(
" fadein " ,
EV_DEFAULT ,
" F[0,]F[0,1] " ,
" fadetime target_alpha " ,
" Fade the entity's alpha and scale in, increasing it by 0.03 \n "
" every FRAMETIME, until it has faded completely in to 1.0. \n "
" If fadetime or target_alpha are defined, they will override \n "
" the default values. " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_Killed (
2023-08-09 23:09:09 +02:00
" killed " ,
EV_DEFAULT ,
" eievvviiii " ,
" attacker damage inflictor position direction normal knockback damageflags meansofdeath location " ,
" event which is sent to an entity once it as been killed \n \n Location values: \n -1 General \n 0 Pelvis \n 1 Lower "
" Torso \n 2 Mid Torso \n 3 Upper Torso \n 4 Neck \n 5 Head \n 6 RUpperArm \n 7 RForearm \n 8 RHand \n 9 LUpperArm \n 10 LForearm \n 11 "
" LHand \n 12 RThigh \n 13 RCalf \n 14 RFoot \n 15 LThigh \n 16 LCalf \n 17 LFoot \n " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_GotKill
2023-08-09 23:09:09 +02:00
(
" gotkill " ,
EV_DEFAULT ,
" eieib " ,
" victim damage inflictor meansofdeath gib " ,
" event sent to attacker when an entity dies " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Pain
2023-08-09 23:09:09 +02:00
(
" pain " ,
EV_DEFAULT ,
" eievvviiii " ,
" attacker damage inflictor position direction normal knockback damageflags meansofdeath location " ,
" used to inflict pain to an entity " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_Damage (
2023-08-09 23:09:09 +02:00
" damage " ,
EV_DEFAULT ,
" eievvviiii " ,
" attacker damage inflictor position direction normal knockback damageflags meansofdeath location " ,
" general damage event used by all entities \n \n Location values: \n -1 General \n 0 Pelvis \n 1 Lower Torso \n 2 Mid "
" Torso \n 3 Upper Torso \n 4 Neck \n 5 Head \n 6 RUpperArm \n 7 RForearm \n 8 RHand \n 9 LUpperArm \n 10 LForearm \n 11 LHand \n 12 "
" RThigh \n 13 RCalf \n 14 RFoot \n 15 LThigh \n 16 LCalf \n 17 LFoot \n " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Stun
2023-08-09 23:09:09 +02:00
(
" _stun " ,
EV_DEFAULT ,
" f " ,
" time " ,
" Stun this entity for the specified time " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Kill
2023-08-09 23:09:09 +02:00
(
" kill " ,
EV_CONSOLE ,
NULL ,
NULL ,
" console based command to kill yourself if stuck. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Gib
2023-08-09 23:09:09 +02:00
(
" gib " ,
EV_DEFAULT ,
" iIFS " ,
" number power scale gibmodel " ,
" causes entity to spawn a number of gibs " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Hurt
2023-08-09 23:09:09 +02:00
(
" hurt " ,
EV_DEFAULT ,
" iSV " ,
" damage means_of_death direction " ,
" Inflicts damage if the entity is damageable. If the number of damage \n "
" points specified in the command argument is greater or equal than the \n "
" entity's current health, it will be killed or destroyed. " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_Heal (
2023-08-09 23:09:09 +02:00
" heal " ,
EV_DEFAULT ,
" f " ,
" health " ,
2023-08-09 23:27:08 +02:00
" Adds health to an entity, "
" 0-1 fraction of max_health "
2016-03-27 11:49:47 +02:00
) ;
Event EV_TakeDamage
2023-08-09 23:09:09 +02:00
(
" takedamage " ,
EV_DEFAULT ,
NULL ,
NULL ,
" makes entity take damage. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_NoDamage
2023-08-09 23:09:09 +02:00
(
" nodamage " ,
EV_DEFAULT ,
NULL ,
NULL ,
" entity does not take damage. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Stationary
2023-08-09 23:09:09 +02:00
(
2023-08-09 23:27:08 +02:00
" stationary " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
NULL ,
NULL ,
2023-08-09 23:27:08 +02:00
" entity does not move, "
" causes no physics to be run on it. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_Toss
2023-08-09 23:09:09 +02:00
(
" toss " ,
EV_DEFAULT ,
NULL ,
NULL ,
" entity has gravity applied to it. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// Physics events
Event EV_MoveDone
2023-08-09 23:09:09 +02:00
(
" movedone " ,
EV_DEFAULT ,
" e " ,
" finishedEntity " ,
" Sent to commanding thread when done with move . " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Touch
2023-08-09 23:09:09 +02:00
(
" doTouch " ,
EV_DEFAULT ,
" e " ,
" touchingEntity " ,
" sent to entity when touched. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Blocked
2023-08-09 23:09:09 +02:00
(
" doBlocked " ,
EV_DEFAULT ,
" e " ,
" obstacle " ,
" sent to entity when blocked. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_UseBoundingBox
2023-08-09 23:09:09 +02:00
(
2023-08-09 23:27:08 +02:00
" usebbox " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
NULL ,
NULL ,
2023-08-09 23:27:08 +02:00
" do not perform perfect collision, "
" use bounding box instead. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Gravity
2023-08-09 23:09:09 +02:00
(
" gravity " ,
EV_DEFAULT ,
" f " ,
" gravityValue " ,
" Change the gravity on this entity " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Stop
2023-08-09 23:09:09 +02:00
(
" stopped " ,
EV_DEFAULT ,
NULL ,
NULL ,
" sent when entity has stopped bouncing for MOVETYPE_TOSS. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Attach
2023-08-09 23:09:09 +02:00
(
" attach " ,
EV_DEFAULT ,
" esI " ,
" parent tagname use_angles " ,
" attach this entity to the parent's legs tag called tagname " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_AttachModel
2023-08-09 23:09:09 +02:00
(
" attachmodel " ,
EV_DEFAULT ,
" ssFSBFFFFV " ,
" modelname tagname scale targetname detach_at_death removetime fadeintime fadeoutdelay fadetime offset " ,
" attach a entity with modelname to this entity to tag called tagname. \n "
" scale - scale of attached entities \n "
" targetname - targetname for attached entities \n "
" detach_at_death - when entity dies, should this model be detached. \n "
" removetime - when the entity should be removed, if not specified, never. \n "
" fadeintime - time to fade the model in over. \n "
" fadeoutdelay - time to wait until we fade the attached model out \n "
" fadeoutspeed - time the model fades out over \n "
" offset - vector offset for the model from the specified tag " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_RemoveAttachedModel
2023-08-09 23:09:09 +02:00
(
" removeattachedmodel " ,
EV_DEFAULT ,
" s " ,
" tagname " ,
" Removes the model attached to this entity at the specified tag. " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_AttachedModelAnim (
2023-08-09 23:09:09 +02:00
" attachedmodelanim " ,
EV_DEFAULT ,
" ssfs " ,
" tagname anim_name crossblend_time model_name " ,
" Tells models (or specified model) attached to specified tag to play \n "
" specified animation. Crossblend time doesn't work yet. "
) ;
2016-03-27 11:49:47 +02:00
Event EV_Detach
2023-08-09 23:09:09 +02:00
(
" detach " ,
EV_DEFAULT ,
NULL ,
NULL ,
" detach this entity from its parent. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// script stuff
Event EV_Model
2023-08-09 23:09:09 +02:00
(
" model " ,
EV_DEFAULT ,
" e " ,
" modelName " ,
" set the model to modelName. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_SetModel
2023-08-09 23:09:09 +02:00
(
" model " ,
EV_DEFAULT ,
" e " ,
" modelName " ,
" set the model to modelName. " ,
EV_SETTER
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetModel
2023-08-09 23:09:09 +02:00
(
" model " ,
EV_DEFAULT ,
NULL ,
NULL ,
" get the modelName. " ,
EV_GETTER
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetBrushModel
2023-08-09 23:09:09 +02:00
(
" brushmodel " ,
EV_DEFAULT ,
NULL ,
NULL ,
" get the brush modelName. " ,
EV_GETTER
) ;
2016-03-27 11:49:47 +02:00
Event EV_Hide
2023-08-09 23:09:09 +02:00
(
2023-08-09 23:27:08 +02:00
" hide " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
NULL ,
NULL ,
2023-08-09 23:27:08 +02:00
" hide the entity, "
" opposite of show. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Show
2023-08-09 23:09:09 +02:00
(
2023-08-09 23:27:08 +02:00
" show " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
NULL ,
NULL ,
2023-08-09 23:27:08 +02:00
" show the entity, "
" opposite of hide. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_BecomeSolid
2023-08-09 23:09:09 +02:00
(
" solid " ,
EV_DEFAULT ,
NULL ,
NULL ,
" make solid. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_SafeSolid
2023-08-09 23:09:09 +02:00
(
" safesolid " ,
EV_DEFAULT ,
NULL ,
NULL ,
" make solid but first make sure no one is in my bounds that is thinking. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_BecomeNonSolid
2023-08-09 23:09:09 +02:00
(
" notsolid " ,
EV_DEFAULT ,
NULL ,
NULL ,
" make non-solid. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Ghost
2023-08-09 23:09:09 +02:00
(
" ghost " ,
EV_DEFAULT ,
NULL ,
NULL ,
" make non-solid but still send to client regardless of hide status. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_TouchTriggers
2023-08-09 23:09:09 +02:00
(
" touchtriggers " ,
EV_DEFAULT ,
NULL ,
NULL ,
" this entity should touch triggers. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Sound
2023-08-09 23:09:09 +02:00
(
" playsound " ,
EV_DEFAULT ,
" sIFS " ,
" soundName channel volume min_distance " ,
" play a sound coming from this entity. \n "
" default channel, CHAN_BODY. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_StopSound
2023-08-09 23:09:09 +02:00
(
" stopsound " ,
EV_DEFAULT ,
" I " ,
" channel " ,
" stop the current sound on the specified channel. \n "
" default channel, CHAN_BODY. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_DuckableGlue
2023-08-09 23:09:09 +02:00
(
" duckableglue " ,
EV_DEFAULT ,
" eI " ,
" parent glueAngles " ,
" glue this entity to the specified entity, but allow ducking. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Glue
2023-08-09 23:09:09 +02:00
(
" glue " ,
EV_DEFAULT ,
" eI " ,
" parent glueAngles " ,
" glue this entity to the specified entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Unglue
2023-08-09 23:09:09 +02:00
(
" unglue " ,
EV_DEFAULT ,
NULL ,
NULL ,
" unglue this entity. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_Bind
2023-08-09 23:09:09 +02:00
(
" bind " ,
EV_DEFAULT ,
" eB " ,
" parent bind_child " ,
" bind this entity to the specified entity. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_Unbind
2023-08-09 23:09:09 +02:00
(
" unbind " ,
EV_DEFAULT ,
NULL ,
NULL ,
" unbind this entity. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_MakeClayPidgeon
2023-08-09 23:09:09 +02:00
(
" claypidgeon " ,
EV_DEFAULT ,
NULL ,
NULL ,
" turn the entity into a non-solid shootable thing " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_JoinTeam
2023-08-09 23:09:09 +02:00
(
" joinTeam " ,
EV_DEFAULT ,
" e " ,
" teamMember " ,
" join a bind team. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_QuitTeam
2023-08-09 23:09:09 +02:00
(
" quitTeam " ,
EV_DEFAULT ,
NULL ,
NULL ,
" quit the current bind team " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetScale
2023-08-09 23:09:09 +02:00
(
" scale " ,
EV_DEFAULT ,
" f " ,
" newScale " ,
" set the scale of the entity " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetScale2
2023-08-09 23:09:09 +02:00
(
" scale " ,
EV_DEFAULT ,
" f " ,
" newScale " ,
" set the scale of the entity " ,
EV_SETTER
) ;
2016-03-27 11:49:47 +02:00
Event EV_GetScale
2023-08-09 23:09:09 +02:00
(
" scale " ,
EV_DEFAULT ,
" f " ,
" newScale " ,
" set the scale of the entity " ,
EV_GETTER
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetSize
2023-08-09 23:09:09 +02:00
(
" setsize " ,
EV_DEFAULT ,
" vv " ,
" mins maxs " ,
" Set the bounding box of the entity to mins and maxs. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetMins
2023-08-09 23:09:09 +02:00
(
" _setmins " ,
EV_DEFAULT ,
" v " ,
" mins " ,
" Set the mins of the bounding box of the entity to mins. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetMaxs
2023-08-09 23:09:09 +02:00
(
" _setmaxs " ,
EV_DEFAULT ,
" v " ,
" maxs " ,
" Set the maxs of the bounding box of the entity to maxs. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetMins
2023-08-09 23:09:09 +02:00
(
" getmins " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Get the mins of the bounding box of the entity to mins. " ,
EV_RETURN
) ;
Event EV_GetMaxs
(
" getmaxs " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Get the maxs of the bounding box of the entity to maxs. " ,
EV_RETURN
) ;
Event EV_SetAlpha
(
" alpha " ,
EV_DEFAULT ,
" f " ,
" newAlpha " ,
" Set the alpha of the entity to alpha. " ,
EV_NORMAL
) ;
Event EV_SetKillTarget
(
" killtarget " ,
EV_DEFAULT ,
" s " ,
" targetName " ,
" when dying kill entities with this targetName. " ,
EV_NORMAL
) ;
Event EV_SetMass
(
" mass " ,
EV_DEFAULT ,
" f " ,
" massAmount " ,
" set the mass of this entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LoopSound
2023-08-09 23:09:09 +02:00
(
" loopsound " ,
EV_DEFAULT ,
" sFS " ,
" soundName volume minimum_distance " ,
" play a looped-sound with a certain volume and minimum_distance \n "
" which is attached to the current entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_StopLoopSound
2023-08-09 23:09:09 +02:00
(
" stoploopsound " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Stop the looped-sound on this entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:27:08 +02:00
Event EV_SurfaceModelEvent (
2023-08-09 23:09:09 +02:00
" surface " ,
EV_DEFAULT ,
" sSSSSSS " ,
" surfaceName parameter1 parameter2 parameter3 parameter4 parameter5 parameter6 " ,
" change a legs surface parameter for the given surface. \n "
" + sets the flag, - clears the flag \n "
" Valid surface commands are: \n "
" skin1 - set the skin1 offset bit \n "
" skin2 - set the skin2 offset bit \n "
" nodraw - don't draw this surface " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// AI sound events
Event EV_BroadcastAIEvent
2023-08-09 23:09:09 +02:00
(
" ai_event " ,
EV_DEFAULT ,
" SF " ,
" type radius " ,
" Let the AI know that this entity made a sound, \n type is a string specifying what type of sound it is. \n radius "
" determines how far the sound reaches. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// Lighting
Event EV_SetLight
2023-08-09 23:09:09 +02:00
(
" light " ,
EV_DEFAULT ,
" ffff " ,
" red green blue radius " ,
2024-09-19 10:52:47 +02:00
" Create a dynamic light on this entity. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightOn
2023-08-09 23:09:09 +02:00
(
" lightOn " ,
EV_DEFAULT ,
NULL ,
NULL ,
2024-09-19 10:52:47 +02:00
" Turn the configured dynamic light on this entity on. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightOff
2023-08-09 23:09:09 +02:00
(
" lightOff " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Turn the configured dynamic light on this entity off. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightStyle
2023-08-09 23:09:09 +02:00
(
" lightStyle " ,
EV_DEFAULT ,
" i " ,
" lightStyleIndex " ,
" What light style to use for this dynamic light on this entity. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightRed
2023-08-09 23:09:09 +02:00
(
" lightRed " ,
EV_DEFAULT ,
" f " ,
" red " ,
2024-09-19 10:52:47 +02:00
" Set the red component of the dynamic light on this entity. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightGreen
2023-08-09 23:09:09 +02:00
(
" lightGreen " ,
EV_DEFAULT ,
" f " ,
" red " ,
2024-09-19 10:52:47 +02:00
" Set the red component of the dynamic light on this entity. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightBlue
2023-08-09 23:09:09 +02:00
(
" lightBlue " ,
EV_DEFAULT ,
" f " ,
" red " ,
2024-09-19 10:52:47 +02:00
" Set the red component of the dynamic light on this entity. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_LightRadius
2023-08-09 23:09:09 +02:00
(
" lightRadius " ,
EV_DEFAULT ,
" f " ,
" red " ,
2024-09-19 10:52:47 +02:00
" Set the red component of the dynamic light on this entity. " ,
2023-08-09 23:09:09 +02:00
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// Entity flag specific
2023-08-09 23:27:08 +02:00
Event EV_EntityFlags (
2023-08-09 23:09:09 +02:00
" flags " ,
EV_DEFAULT ,
" SSSSSS " ,
" parameter1 parameter2 parameter3 parameter4 parameter5 parameter6 " ,
" Change the current entity flags. \n "
" Valid flags are as follows: \n "
" + sets a flag, - clears a flag \n "
" blood - should it bleed \n "
" explode - should it explode when dead \n "
" die_gibs - should it spawn gibs when dead \n "
" god - makes the entity invincible \n " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_EntityRenderEffects (
2023-08-09 23:09:09 +02:00
" rendereffects " ,
EV_DEFAULT ,
" SSSSSS " ,
" parameter1 parameter2 parameter3 parameter4 parameter5 parameter6 " ,
" Change the current render effects flags. \n "
" Valid flags are as follows: \n "
" + sets a flag, - clears a flag \n "
" dontdraw - send the entity to the client, but don't draw \n "
" betterlighting - do sphere based vertex lighting on the entity \n "
" lensflare - add a lens glow to the entity at its origin \n "
" viewlensflare - add a view dependent lens glow to the entity at its origin \n "
" lightoffset - use the dynamic color values as a light offset to the model \n "
" skyorigin - this entity is the portal sky origin \n "
" minlight - this entity always has some lighting on it \n "
" fullbright - this entity is always fully lit \n "
" additivedynamiclight - the dynamic light should have an additive effect \n "
" lightstyledynamiclight - the dynamic light uses a light style, use the \n "
" 'lightstyle' command to set the index of the light style to be used " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_EntityEffects (
2023-08-09 23:09:09 +02:00
" effects " ,
EV_DEFAULT ,
" SSSSSS " ,
" parameter1 parameter2 parameter3 parameter4 parameter5 parameter6 " ,
" Change the current entity effects flags. \n "
" Valid flags are as follows: \n "
" + sets a flag, - clears a flag \n "
" antisbjuice - anti sucknblow juice "
" everyframe - process commands every time entity is rendered " ,
EV_NORMAL
) ;
2023-08-09 23:27:08 +02:00
Event EV_EntitySVFlags (
2023-08-09 23:09:09 +02:00
" svflags " ,
EV_DEFAULT ,
" SSSSSS " ,
" parameter1 parameter2 parameter3 parameter4 parameter5 parameter6 " ,
" Change the current server flags. \n "
" Valid flags are as follows: \n "
" + sets a flag, - clears a flag \n "
" broadcast - always send this entity to the client " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
// Special Effects
Event EV_Censor
2023-08-09 23:09:09 +02:00
(
" censor " ,
EV_DEFAULT ,
NULL ,
NULL ,
" used to ban certain contact when in parentmode \n " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Explosion
2023-08-09 23:09:09 +02:00
(
" explosionattack " ,
EV_DEFAULT ,
" sS " ,
" explosionModel tagName " ,
" Spawn an explosion optionally from a specific tag " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_ShaderEvent
2023-08-09 23:09:09 +02:00
(
" shader " ,
EV_DEFAULT ,
" sfF " ,
" shaderCommand argument1 argument2 " ,
" change a specific shader parameter for the entity. \n "
" Valid shader commands are: \n "
" translation [trans_x] [trans_y] - change the texture translation \n "
" offset [offset_x] [offset_y] - change the texture offset \n "
" rotation [rot_speed] - change the texture rotation speed \n "
" frame [frame_num] - change the animated texture frame \n "
" wavebase [base] - change the base parameter of the wave function \n "
" waveamp [amp] - change the amp parameter of the wave function \n "
" wavebase [phase] - change the phase parameter of the wave function \n "
" wavefreq [freq] - change the frequency parameter of the wave function \n " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_ScriptShaderEvent
2023-08-09 23:09:09 +02:00
(
" scriptshader " ,
EV_DEFAULT ,
" sfF " ,
" shaderCommand argument1 argument2 " ,
" alias for shader command, change a specific shader parameter for the entity. \n "
" Valid shader commands are: \n "
" translation [trans_x] [trans_y] - change the texture translation \n "
" offset [offset_x] [offset_y] - change the texture offset \n "
" rotation [rot_speed] - change the texture rotation speed \n "
" frame [frame_num] - change the animated texture frame \n "
" wavebase [base] - change the base parameter of the wave function \n "
" waveamp [amp] - change the amp parameter of the wave function \n "
" wavebase [phase] - change the phase parameter of the wave function \n "
" wavefreq [freq] - change the frequency parameter of the wave function \n " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_KillAttach
2023-08-09 23:09:09 +02:00
(
" killattach " ,
EV_DEFAULT ,
NULL ,
NULL ,
" kill all the attached entities. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_DropToFloor
2023-08-09 23:09:09 +02:00
(
" droptofloor " ,
EV_DEFAULT ,
" F " ,
" maxRange " ,
" drops the entity to the ground, if maxRange is not specified 8192 is used. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_AddToSoundManager
2023-08-09 23:09:09 +02:00
(
" _addtosoundmanager " ,
EV_DEFAULT ,
NULL ,
NULL ,
" adds the current entity to the sound manager. " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_SetControllerAngles
2023-08-09 23:09:09 +02:00
(
" setcontrollerangles " ,
EV_DEFAULT ,
" iv " ,
" num angles " ,
" Sets the control angles for the specified bone. " ,
EV_NORMAL
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetControllerAngles
2023-08-09 23:09:09 +02:00
(
2023-07-30 21:21:00 +02:00
" getcontrollerangles " ,
EV_DEFAULT ,
" i " ,
" num " ,
" Gets the control angles for the specified bone. " ,
EV_RETURN
2023-08-09 23:09:09 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetTagPosition
2023-08-09 23:09:09 +02:00
(
" gettagposition " ,
EV_DEFAULT ,
" s " ,
" tag_name " ,
" Gets the world position of the tag " ,
EV_RETURN
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetTagAngles
2023-08-09 23:09:09 +02:00
(
" gettagangles " ,
EV_DEFAULT ,
" s " ,
" tag_name " ,
" Gets the world angles of the tag " ,
EV_RETURN
) ;
2016-03-27 11:49:47 +02:00
Event EV_DeathSinkStart
2023-08-09 23:09:09 +02:00
(
" deathsinkstart " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Makes the entity sink into the ground and then get removed (this starts it). " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_DeathSink
2023-08-09 23:09:09 +02:00
(
" deathsinkeachframe " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Makes the entity sink into the ground and then get removed (this gets called each frame). " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_DamageType
2023-08-09 23:09:09 +02:00
(
" damage_type " ,
EV_DEFAULT ,
" s " ,
" meansofdeathstring " ,
" Set the type of damage that this entity can take " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_DetachAllChildren
(
2023-08-09 23:09:09 +02:00
" detachallchildren " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Detach all the children from the entity. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_MovementStealth
(
2023-08-09 23:09:09 +02:00
" movementstealth " ,
EV_DEFAULT ,
" f " ,
" scale " ,
" Sets the current movement stealth scalar for the sentient " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_Entity_Revive
(
" revive " ,
EV_DEFAULT ,
" f " ,
" health " ,
2023-08-09 23:27:08 +02:00
" sets the health, "
" even if dead "
2023-07-30 21:21:00 +02:00
) ;
Event EV_SetHealth
(
2023-08-09 23:09:09 +02:00
" health " ,
EV_CONSOLE | EV_CHEAT ,
" i " ,
" newHealth " ,
" set the health of the entity to newHealth " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_SetHealth2
(
2023-08-09 23:09:09 +02:00
" health " ,
EV_CONSOLE | EV_CHEAT ,
" i " ,
" newHealth " ,
" set the health of the entity to newHealth " ,
EV_SETTER
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_GetHealth
(
2023-08-09 23:09:09 +02:00
" health " ,
EV_DEFAULT ,
NULL ,
NULL ,
" entity's health " ,
EV_GETTER
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_GetMaxHealth
(
2023-08-09 23:09:09 +02:00
" max_health " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets the entity's max health " ,
EV_GETTER
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_SetMaxHealth
(
2023-08-09 23:09:09 +02:00
" max_health " ,
EV_DEFAULT ,
" i " ,
" newHealth " ,
" sets max_health without changing health " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_SetMaxHealth2
(
2023-08-09 23:09:09 +02:00
" max_health " ,
EV_DEFAULT ,
" i " ,
" newHealth " ,
" sets max_health without changing health " ,
EV_SETTER
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_SetHealthOnly
(
2023-08-09 23:09:09 +02:00
" healthonly " ,
EV_CONSOLE | EV_CHEAT ,
" i " ,
" newHealth " ,
" set the health of the entity to newHealth without changing max_health " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_SetHealthOnly2
(
2023-08-09 23:09:09 +02:00
" healthonly " ,
EV_CONSOLE | EV_CHEAT ,
" i " ,
" newHealth " ,
" set the health of the entity to newHealth without changing max_health " ,
EV_SETTER
2023-07-30 21:21:00 +02:00
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_GetYaw
(
2023-08-09 23:09:09 +02:00
" yaw " ,
EV_DEFAULT ,
NULL ,
NULL ,
" entity's yaw " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_Pusher
(
2023-08-09 23:09:09 +02:00
" pusher " ,
EV_DEFAULT ,
" eevf " ,
" inflictor attacker direction force " ,
" Push an entity in the specified direction with the specified force " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_NeverDraw
(
2023-08-09 23:09:09 +02:00
" neverdraw " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Sets this entity to never draw " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_NormalDraw
(
2023-08-09 23:09:09 +02:00
" normaldraw " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Sets this entity to normal draw " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_AlwaysDraw
(
2023-08-09 23:09:09 +02:00
" alwaysdraw " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Sets this entity to always draw " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_IsTouching
(
2023-08-09 23:27:08 +02:00
" istouching " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
" e " ,
" ent " ,
2023-08-09 23:27:08 +02:00
" returns 1 if the entities are touching, "
" 0 if not " ,
2023-08-09 23:09:09 +02:00
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_IsInside
(
2023-08-09 23:27:08 +02:00
" isinside " ,
EV_DEFAULT ,
2023-07-30 21:21:00 +02:00
" e " ,
" ent " ,
2023-08-09 23:27:08 +02:00
" returns 1 if the entity is inside, "
" 0 if not " ,
2023-07-30 21:21:00 +02:00
EV_RETURN
) ;
2016-03-27 11:49:47 +02:00
Event EV_CanSee
(
2023-08-09 23:09:09 +02:00
" cansee " ,
EV_DEFAULT ,
" eFF " ,
" entity fov vision_distance " ,
" returns 1 if the entities can see eachother, 0 if not " ,
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_CanSeeNoEnts
(
2023-08-12 19:59:17 +02:00
" canseenoents " ,
2023-07-30 21:21:00 +02:00
EV_DEFAULT ,
" eFF " ,
" entity fov vision_distance " ,
" returns 1 if the entities can see eachother, 0 if not; ignores any entities between them " ,
EV_RETURN
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_InPVS
(
2023-08-09 23:27:08 +02:00
" inpvs " ,
EV_DEFAULT ,
2023-08-09 23:09:09 +02:00
" e " ,
" entity " ,
2023-08-09 23:27:08 +02:00
" returns 1 if the entities have connected pvs, "
" 0 if not " ,
2023-08-09 23:09:09 +02:00
EV_RETURN
2016-03-27 11:49:47 +02:00
) ;
Event EV_SetShaderData
(
2023-08-09 23:09:09 +02:00
" setshaderdata " ,
EV_DEFAULT ,
" ff " ,
" data0 data1 " ,
" sets the shader controllers for this entity. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_SetVelocity
2016-03-27 11:49:47 +02:00
(
2023-08-09 23:09:09 +02:00
" velocity " ,
EV_DEFAULT ,
" v " ,
" velocity " ,
" sets the velocity for this entity. " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetVelocity
2016-03-27 11:49:47 +02:00
(
2023-08-09 23:09:09 +02:00
" velocity " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets the velocity for this entity. " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_GetAVelocity
(
2023-08-09 23:09:09 +02:00
" avelocity " ,
EV_DEFAULT ,
NULL ,
NULL ,
" gets the angular velocity for this entity. " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_ForceActivate
(
2023-08-09 23:09:09 +02:00
" forceactivate " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Forces an entity to activate outside of the player's PVS " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_ConnectPaths
(
" connect_paths " ,
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-09 23:09:09 +02:00
" Connects all navigation paths which intersect with the specified entity's volume " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2016-03-27 11:49:47 +02:00
Event EV_DisconnectPaths
(
2023-08-09 23:09:09 +02:00
" disconnect_paths " ,
EV_DEFAULT ,
NULL ,
NULL ,
" disonnects all navigation paths which intersect with the specified entity's volume " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_VolumeDamage
(
2023-07-30 21:21:00 +02:00
" volumedamage " ,
EV_DEFAULT ,
" f " ,
" damage " ,
2023-08-09 23:09:09 +02:00
" does damage to any entity within this's volume " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_AddImmunity
(
2023-07-30 21:21:00 +02:00
" immune " ,
EV_DEFAULT ,
" sSSSSS " ,
" immune_string1 immune_string2 immune_string3 immune_string4 immune_string5 immune_string6 " ,
2023-08-09 23:09:09 +02:00
" Adds to the immunity list for this sentient. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_RemoveImmunity
(
2023-07-30 21:21:00 +02:00
" removeimmune " ,
EV_DEFAULT ,
" sSSSSS " ,
" immune_string1 immune_string2 immune_string3 immune_string4 immune_string5 immune_string6 " ,
2023-08-09 23:09:09 +02:00
" Removes from the immunity list for this sentient. " ,
EV_NORMAL
2016-03-27 11:49:47 +02:00
) ;
Event EV_GetEntnum
(
2023-08-09 23:09:09 +02:00
" entnum " ,
EV_DEFAULT ,
NULL ,
NULL ,
" The entity's entity number " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-07-30 21:21:00 +02:00
Event EV_GetClassname
(
" classname " ,
EV_DEFAULT ,
NULL ,
NULL ,
" The entity's classname " ,
EV_GETTER
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_SetRadnum
(
2023-08-09 23:09:09 +02:00
" radnum " ,
EV_DEFAULT ,
" i " ,
" radnum " ,
" set the radnum " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_GetRadnum
(
2023-08-09 23:09:09 +02:00
" radnum " ,
EV_DEFAULT ,
NULL ,
NULL ,
" entity's radnum " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_SetRotatedBbox
(
2023-08-09 23:09:09 +02:00
" rotatedbbox " ,
EV_DEFAULT ,
" i " ,
" on_off " ,
" Sets the entity's bbox to rotate with it. " ,
EV_SETTER
2016-03-27 11:49:47 +02:00
) ;
Event EV_Entity_GetRotatedBbox
(
2023-08-09 23:09:09 +02:00
" rotatedbbox " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets te entity's bbox to rotate with it. " ,
EV_GETTER
2016-03-27 11:49:47 +02:00
) ;
2023-08-09 23:27:08 +02:00
Event EV_Entity_SinglePlayerCommand
(
" sp " ,
EV_DEFAULT ,
" sSSS " ,
2023-12-28 20:50:47 +01:00
" command parm1 parm2 ... " ,
2023-08-09 23:27:08 +02:00
" Makes a command be executed only in single player " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2023-08-09 23:27:08 +02:00
Event EV_Entity_MultiPlayerCommand
(
" dm " ,
EV_DEFAULT ,
" sSSS " ,
2023-12-28 20:50:47 +01:00
" command parm1 parm2 ... " ,
2023-08-09 23:27:08 +02:00
" Makes a command be executed only in multiplayer " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2023-08-09 23:27:08 +02:00
Event EV_Entity_RealismModeCommand
(
" realism " ,
EV_DEFAULT ,
" sSSS " ,
2023-12-28 20:50:47 +01:00
" command parm1 parm2 ... " ,
2023-08-09 23:27:08 +02:00
" Makes a command be executed only in realism mode " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2023-08-09 23:27:08 +02:00
Event EV_Entity_SPRealismModeCommand
(
" sprealism " ,
EV_DEFAULT ,
" sSSS " ,
2023-12-28 20:50:47 +01:00
" command parm1 parm2 ... " ,
2023-08-09 23:27:08 +02:00
" Makes a command be executed only in single player realism mode " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2023-08-09 23:27:08 +02:00
Event EV_Entity_DMRealismModeCommand
(
" dmrealism " ,
EV_DEFAULT ,
" sSSS " ,
2023-12-28 20:50:47 +01:00
" command parm1 parm2 ... " ,
2023-08-09 23:27:08 +02:00
" Makes a command be executed only in multiplayer realism mode " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_Entity_GetLocalYawFromVector
(
" GetLocalYawFromVector " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Turn a worldspace vector into a local space yaw " ,
2023-10-18 19:53:04 +02:00
EV_RETURN
2023-07-30 21:21:00 +02:00
) ;
Event EV_ShootableOnly
(
" shootableonly " ,
EV_DEFAULT ,
NULL ,
NULL ,
2023-08-09 23:09:09 +02:00
" Makes the entity shootable only. " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_SetShaderTime
(
" setshadertime " ,
EV_DEFAULT ,
" FF " ,
" timeOffset randomTimeOffset " ,
2023-08-09 23:09:09 +02:00
" reset the shader time for this entity. " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
Event EV_NoTarget
(
" notarget " ,
EV_DEFAULT ,
" b " ,
" setNoTarget " ,
2023-08-09 23:09:09 +02:00
" flag an entity as no target. " ,
EV_NORMAL
2023-07-30 21:21:00 +02:00
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_SetDHack
2023-08-09 23:09:09 +02:00
(
" depthhack " ,
EV_DEFAULT ,
" i " ,
" bEnable " ,
" Enable or disable depth hack. " ,
EV_NORMAL
) ;
2024-05-27 23:28:12 +02:00
/*
2016-03-27 11:49:47 +02:00
Event EV_Entity_GetZone
2023-08-09 23:09:09 +02:00
(
" getzone " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Gets the current entity zone. NIL if the entity is not in a zone. " ,
EV_RETURN
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_Zone
2023-08-09 23:09:09 +02:00
(
" zone " ,
EV_DEFAULT ,
NULL ,
NULL ,
" Get the current entity zone. NIL if the entity is not in a zone. " ,
EV_GETTER
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_IsInZone
2023-08-09 23:09:09 +02:00
(
" isinzone " ,
EV_DEFAULT ,
" e " ,
" zone " ,
" Returns 1 if the entity is in the specified zone. 0 otherwise " ,
EV_RETURN
) ;
2024-05-27 23:28:12 +02:00
*/
2016-03-27 11:49:47 +02:00
Event EV_Entity_SetHintRequireLookAt
2023-08-09 23:09:09 +02:00
(
" setuselookat " ,
EV_DEFAULT ,
" b " ,
" lookat " ,
" Sets if the client must look at the entity to use it " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_SetHintString
2023-08-09 23:09:09 +02:00
(
" sethintstring " ,
EV_DEFAULT ,
" s " ,
" string " ,
" Sets the hint string for an entity when touching it. '&&1' will be replaced by the +use key on the client. If "
" hideent/hide is called on this entity, the hint string won't be shown for the client " ,
EV_NORMAL
) ;
2016-03-27 11:49:47 +02:00
Event EV_Entity_SetShader
2023-08-09 23:09:09 +02:00
(
" setshader " ,
EV_DEFAULT ,
" s " ,
" shadername " ,
" Sets a shader for the entity. An empty string will revert to the normal entity shader. " ,
EV_NORMAL
) ;
CLASS_DECLARATION ( SimpleEntity , Entity , NULL ) {
{ & EV_Damage , & Entity : : DamageEvent } ,
{ & EV_DamageType , & Entity : : DamageType } ,
{ & EV_Kill , & Entity : : Kill } ,
{ & EV_Killed , & Entity : : Killed } ,
{ & EV_FadeNoRemove , & Entity : : FadeNoRemove } ,
{ & EV_FadeOut , & Entity : : FadeOut } ,
{ & EV_FadeIn , & Entity : : FadeIn } ,
{ & EV_Fade , & Entity : : Fade } ,
{ & EV_Hide , & Entity : : EventHideModel } ,
{ & EV_Show , & Entity : : EventShowModel } ,
{ & EV_BecomeSolid , & Entity : : BecomeSolid } ,
{ & EV_SafeSolid , & Entity : : SafeSolid } ,
{ & EV_BecomeNonSolid , & Entity : : BecomeNonSolid } ,
{ & EV_Ghost , & Entity : : Ghost } ,
{ & EV_TouchTriggers , & Entity : : TouchTriggersEvent } ,
{ & EV_Sound , & Entity : : Sound } ,
{ & EV_StopSound , & Entity : : StopSound } ,
{ & EV_SetSize , & Entity : : SetSize } ,
{ & EV_SetMins , & Entity : : SetMins } ,
{ & EV_SetMaxs , & Entity : : SetMaxs } ,
{ & EV_GetMins , & Entity : : GetMins } ,
{ & EV_GetMaxs , & Entity : : GetMaxs } ,
{ & EV_SetScale , & Entity : : SetScale } ,
{ & EV_SetScale2 , & Entity : : SetScale } ,
{ & EV_GetScale , & Entity : : GetScale } ,
{ & EV_SetAlpha , & Entity : : SetAlpha } ,
{ & EV_SetKillTarget , & Entity : : SetKillTarget } ,
{ & EV_SetMass , & Entity : : SetMassEvent } ,
{ & EV_LoopSound , & Entity : : LoopSound } ,
{ & EV_StopLoopSound , & Entity : : StopLoopSound } ,
{ & EV_Model , & Entity : : SetModelEvent } ,
{ & EV_SetModel , & Entity : : SetModelEvent } ,
{ & EV_GetModel , & Entity : : GetModelEvent } ,
{ & EV_GetBrushModel , & Entity : : GetBrushModelEvent } ,
{ & EV_SetLight , & Entity : : SetLight } ,
{ & EV_LightOn , & Entity : : LightOn } ,
{ & EV_LightOff , & Entity : : LightOff } ,
{ & EV_LightRed , & Entity : : LightRed } ,
{ & EV_LightGreen , & Entity : : LightGreen } ,
{ & EV_LightBlue , & Entity : : LightBlue } ,
{ & EV_LightRadius , & Entity : : LightRadius } ,
{ & EV_LightStyle , & Entity : : LightStyle } ,
{ & EV_EntityFlags , & Entity : : Flags } ,
{ & EV_EntityEffects , & Entity : : Effects } ,
{ & EV_EntitySVFlags , & Entity : : SVFlags } ,
{ & EV_EntityRenderEffects , & Entity : : RenderEffects } ,
{ & EV_BroadcastAIEvent , & Entity : : BroadcastAIEvent } ,
{ & EV_SurfaceModelEvent , & Entity : : SurfaceModelEvent } ,
{ & EV_Attach , & Entity : : AttachEvent } ,
{ & EV_AttachModel , & Entity : : AttachModelEvent } ,
{ & EV_RemoveAttachedModel , & Entity : : RemoveAttachedModelEvent } ,
{ & EV_AttachedModelAnim , & Entity : : AttachedModelAnimEvent } ,
{ & EV_Detach , & Entity : : DetachEvent } ,
{ & EV_TakeDamage , & Entity : : TakeDamageEvent } ,
{ & EV_NoDamage , & Entity : : NoDamageEvent } ,
{ & EV_Gravity , & Entity : : Gravity } ,
{ & EV_UseBoundingBox , & Entity : : UseBoundingBoxEvent } ,
{ & EV_Hurt , & Entity : : HurtEvent } ,
{ & EV_Heal , & Entity : : HealEvent } ,
{ & EV_Classname , & Entity : : ClassnameEvent } ,
{ & EV_SoundDone , & Entity : : EventSoundDone } ,
{ & EV_SpawnFlags , & Entity : : SpawnFlagsEvent } ,
{ & EV_SetTeam , & Entity : : SetTeamEvent } ,
{ & EV_Trigger , & Entity : : TriggerEvent } ,
{ & EV_Censor , & Entity : : Censor } ,
{ & EV_Stationary , & Entity : : StationaryEvent } ,
{ & EV_Toss , & Entity : : TossEvent } ,
{ & EV_Explosion , & Entity : : Explosion } ,
{ & EV_ShaderEvent , & Entity : : Shader } ,
{ & EV_ScriptShaderEvent , & Entity : : Shader } ,
{ & EV_KillAttach , & Entity : : KillAttach } ,
{ & EV_DropToFloor , & Entity : : DropToFloorEvent } ,
{ & EV_Glue , & Entity : : GlueEvent } ,
{ & EV_DuckableGlue , & Entity : : DuckableGlueEvent } ,
{ & EV_Unglue , & Entity : : EventUnglue } ,
{ & EV_Bind , & Entity : : BindEvent } ,
{ & EV_Unbind , & Entity : : EventUnbind } ,
{ & EV_MakeClayPidgeon , & Entity : : MakeClayPidgeon } ,
{ & EV_JoinTeam , & Entity : : JoinTeam } ,
{ & EV_QuitTeam , & Entity : : EventQuitTeam } ,
{ & EV_AddToSoundManager , & Entity : : AddToSoundManager } ,
{ & EV_SetControllerAngles , & Entity : : SetControllerAngles } ,
{ & EV_GetControllerAngles , & Entity : : GetControllerAngles } ,
{ & EV_GetTagPosition , & Entity : : GetTagPosition } ,
{ & EV_GetTagAngles , & Entity : : GetTagAngles } ,
{ & EV_DeathSinkStart , & Entity : : DeathSinkStart } ,
{ & EV_DeathSink , & Entity : : DeathSink } ,
{ & EV_DetachAllChildren , & Entity : : DetachAllChildren } ,
{ & EV_Entity_MovementStealth , & Entity : : EventMovementStealth } ,
{ & EV_Pusher , & Entity : : PusherEvent } ,
{ & EV_AlwaysDraw , & Entity : : AlwaysDraw } ,
{ & EV_NeverDraw , & Entity : : NeverDraw } ,
{ & EV_NormalDraw , & Entity : : NormalDraw } ,
{ & EV_IsTouching , & Entity : : IsTouching } ,
{ & EV_IsInside , & Entity : : IsInside } ,
{ & EV_CanSee , & Entity : : CanSee } ,
{ & EV_Entity_InPVS , & Entity : : EventInPVS } ,
{ & EV_SetShaderData , & Entity : : SetShaderData } ,
{ & EV_GetVelocity , & Entity : : GetVelocity } ,
{ & EV_SetVelocity , & Entity : : SetVelocity } ,
{ & EV_GetAVelocity , & Entity : : GetAVelocity } ,
{ & EV_ForceActivate , & Entity : : ForceActivate } ,
{ & EV_ScriptThread_Trace , & Entity : : EventTrace } ,
{ & EV_ScriptThread_SightTrace , & Entity : : EventSightTrace } ,
{ & EV_Entity_Revive , & Entity : : EventRevive } ,
{ & EV_SetHealth , & Entity : : SetHealth } ,
{ & EV_SetHealth2 , & Entity : : SetHealth } ,
{ & EV_Entity_GetHealth , & Entity : : GetHealth } ,
{ & EV_Entity_GetMaxHealth , & Entity : : EventGetMaxHealth } ,
{ & EV_Entity_SetMaxHealth , & Entity : : EventSetMaxHealth } ,
{ & EV_Entity_SetMaxHealth2 , & Entity : : EventSetMaxHealth } ,
{ & EV_Entity_SetHealthOnly , & Entity : : EventSetHealthOnly } ,
{ & EV_Entity_SetHealthOnly2 , & Entity : : EventSetHealthOnly } ,
{ & EV_Entity_GetYaw , & Entity : : GetYaw } ,
{ & EV_ConnectPaths , & Entity : : EventConnectPaths } ,
{ & EV_DisconnectPaths , & Entity : : EventDisconnectPaths } ,
{ & EV_Remove , & Entity : : Remove } ,
2024-02-04 19:09:08 +01:00
{ & EV_Delete , & Listener : : ScriptRemove } ,
{ & EV_ScriptRemove , & Listener : : ScriptRemove } ,
2023-08-09 23:09:09 +02:00
{ & EV_VolumeDamage , & Entity : : EventVolumeDamage } ,
{ & EV_GetNormalHealth , & Entity : : EventGetNormalHealth } ,
{ & EV_NormalDamage , & Entity : : EventNormalDamage } ,
{ & EV_Entity_AddImmunity , & Entity : : AddImmunity } ,
{ & EV_Entity_RemoveImmunity , & Entity : : RemoveImmunity } ,
{ & EV_GetEntnum , & Entity : : EventGetEntnum } ,
{ & EV_GetClassname , & Entity : : EventGetClassname } ,
{ & EV_Entity_SetRadnum , & Entity : : EventSetRadnum } ,
{ & EV_Entity_GetRadnum , & Entity : : EventGetRadnum } ,
{ & EV_Entity_SetRotatedBbox , & Entity : : EventSetRotatedBbox } ,
{ & EV_Entity_GetRotatedBbox , & Entity : : EventGetRotatedBbox } ,
{ & EV_Entity_SinglePlayerCommand , & Entity : : EventSinglePlayerCommand } ,
{ & EV_Entity_MultiPlayerCommand , & Entity : : EventMultiPlayerCommand } ,
{ & EV_Entity_RealismModeCommand , & Entity : : EventRealismModeCommand } ,
{ & EV_Entity_SPRealismModeCommand , & Entity : : EventSPRealismModeCommand } ,
{ & EV_Entity_DMRealismModeCommand , & Entity : : EventDMRealismModeCommand } ,
{ & EV_Entity_GetLocalYawFromVector , & Entity : : GetLocalYawFromVector } ,
{ & EV_ShootableOnly , & Entity : : EventShootableOnly } ,
{ & EV_SetShaderTime , & Entity : : SetShaderTime } ,
{ & EV_NoTarget , & Entity : : NoTarget } ,
2024-05-27 23:28:12 +02:00
/*
2023-08-09 23:09:09 +02:00
{ & EV_Entity_GetZone , & Entity : : GetZone } ,
{ & EV_Entity_Zone , & Entity : : GetZone } ,
{ & EV_Entity_IsInZone , & Entity : : IsInZone } ,
2024-05-27 23:28:12 +02:00
*/
2023-08-09 23:09:09 +02:00
{ & EV_Entity_SetDHack , & Entity : : SetDepthHack } ,
{ & EV_Entity_SetHintRequireLookAt , & Entity : : SetHintRequireLookAt } ,
{ & EV_Entity_SetHintString , & Entity : : SetHintString } ,
{ & EV_Entity_SetShader , & Entity : : SetShader } ,
{ NULL , NULL }
} ;
2016-03-27 11:49:47 +02:00
Entity : : Entity ( )
{
2023-08-09 23:09:09 +02:00
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
edict = level . AllocEdict ( this ) ;
client = edict - > client ;
entnum = edict - > s . number ;
radnum = - 1 ;
2016-03-27 11:49:47 +02:00
2023-11-16 23:11:48 +01:00
entflags | = ECF_ENTITY ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
AddWaitTill ( STRING_DAMAGE ) ;
AddWaitTill ( STRING_SPAWN ) ;
AddWaitTill ( STRING_SOUNDDONE ) ;
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
if ( LoadingSavegame ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
edict - > tiki = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// spawning variables
spawnflags = level . spawnflags ;
level . spawnflags = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// rendering variables
setAlpha ( 1.0f ) ;
setScale ( 1.0f ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// physics variables
mass = 0 ;
gravity = 1.0 ;
groundentity = NULL ;
groundcontents = 0 ;
velocity = vec_zero ;
avelocity = vec_zero ;
2023-11-13 00:58:33 +01:00
edict - > clipmask = MASK_SOLID ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
m_iNumGlues = 0 ;
m_bGlueAngles = true ;
m_pGlueMaster = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// team variables
teamchain = NULL ;
teammaster = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// bind variables
bindmaster = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// this is an generic entity
edict - > s . eType = ET_GENERAL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setContents ( 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
edict - > s . parent = ENTITYNUM_NONE ;
edict - > r . ownerNum = ENTITYNUM_NONE ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// model binding variables
numchildren = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < MAX_MODEL_CHILDREN ; i + + ) {
children [ i ] = ENTITYNUM_NONE ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( int i = 0 ; i < MAX_GLUE_CHILDREN ; i + + ) {
m_pGluesFlags [ i ] = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setOrigin ( vec_zero ) ;
origin . copyTo ( edict - > s . origin2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setAngles ( vec_zero ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setMoveType ( MOVETYPE_NONE ) ;
setSolidType ( SOLID_NOT ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Character state
health = 0 ;
max_health = 0 ;
deadflag = DEAD_NO ;
flags = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// underwater variables
watertype = 0 ;
waterlevel = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Pain and damage variables
takedamage = DAMAGE_NO ;
enemy = NULL ;
pain_finished = 0 ;
damage_debounce_time = 0 ;
damage_type = - 1 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
detach_at_death = qtrue ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Light variables
lightRadius = 0 ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
stealthMovementScale = 1.0f ;
m_iNumBlockedPaths = 0 ;
m_BlockedPaths = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
m_bHintRequiresLookAt = true ;
2016-03-27 11:49:47 +02:00
}
Entity : : ~ Entity ( )
{
2023-08-09 23:09:09 +02:00
Container < Entity * > bindlist ;
Container < Entity * > gluelist ;
Entity * ent ;
int num ;
int i ;
// unbind any entities that are bound to me
// can't unbind within this loop, so make an array
// and unbind them outside of it.
num = 0 ;
for ( ent = teamchain ; ent ; ent = ent - > teamchain ) {
if ( ent - > bindmaster = = this ) {
bindlist . AddObject ( ent ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
num = bindlist . NumObjects ( ) ;
for ( i = 1 ; i < = num ; i + + ) {
bindlist . ObjectAt ( i ) - > unbind ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// detach all glued entities
num = 0 ;
for ( i = 0 ; i < m_iNumGlues ; i + + ) {
if ( m_pGlues [ i ] & & m_pGlues [ i ] - > m_pGlueMaster = = this ) {
gluelist . AddObject ( m_pGlues [ i ] ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
num = gluelist . NumObjects ( ) ;
for ( i = 1 ; i < = num ; i + + ) {
gluelist . ObjectAt ( i ) - > unglue ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
bindlist . FreeObjectList ( ) ;
gluelist . FreeObjectList ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
unbind ( ) ;
quitTeam ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
unglue ( ) ;
detach ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//
// go through and set our children
//
num = numchildren ;
for ( i = 0 ; ( i < MAX_MODEL_CHILDREN ) & & num ; i + + ) {
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
ent = G_GetEntity ( children [ i ] ) ;
if ( ent ) {
ent - > PostEvent ( EV_Remove , 0 ) ;
}
num - - ;
}
if ( m_BlockedPaths ) {
2024-06-23 00:24:20 +02:00
delete [ ] m_BlockedPaths ;
m_BlockedPaths = NULL ;
2023-08-09 23:09:09 +02:00
}
level . FreeEdict ( edict ) ;
2023-11-16 23:11:48 +01:00
entflags & = ~ ECF_ENTITY ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : ClassnameEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
strncpy ( edict - > entname , ev - > GetString ( 1 ) , sizeof ( edict - > entname ) - 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SpawnFlagsEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
// spawning variables
spawnflags = ev - > GetInteger ( 1 ) ;
if ( spawnflags & SPAWNFLAG_DETAIL ) {
edict - > s . renderfx | = RF_DETAIL ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventRevive ( Event * ev )
{
float multiplier = 1.0f ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ev - > IsFromScript ( ) & & IsSubclassOfSentient ( ) ) {
Sentient * pThis = static_cast < Sentient * > ( this ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( pThis - > m_Team = = TEAM_AMERICAN ) {
switch ( skill - > integer ) {
case 0 :
multiplier = 1.3f ;
break ;
case 1 :
multiplier = 1.0f ;
break ;
case 2 :
multiplier = 0.7f ;
break ;
}
} else {
switch ( skill - > integer ) {
case 0 :
multiplier = 0.7f ;
break ;
case 1 :
multiplier = 1.0f ;
break ;
case 2 :
multiplier = 1.3f ;
break ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
health = ev - > GetFloat ( 1 ) * multiplier ;
if ( health < = 0.f ) {
throw ScriptException ( " health must be greated than 0 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
deadflag = DEAD_NO ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetHealth ( Event * ev )
{
if ( IsDead ( ) ) {
ScriptError ( " cannot give health to dead entities " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
health = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( health < = 0 ) {
ScriptError ( " health must be greater than 0 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
max_health = health ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetHealth ( Event * ev )
{
ev - > AddFloat ( health ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventSetMaxHealth ( Event * ev )
{
max_health = ev - > GetFloat ( 1 ) ;
if ( max_health < = 0.0f ) {
ScriptError ( " max_health must be greater than 0 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( health > max_health ) {
health = max_health ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventGetMaxHealth ( Event * ev )
{
ev - > AddFloat ( max_health ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventSetHealthOnly ( Event * ev )
{
if ( IsDead ( ) ) {
ScriptError ( " cannot give health to dead entities " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
health = ev - > GetFloat ( 1 ) ;
if ( health < = 0.0f ) {
ScriptError ( " health must be greater than 0 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( health > max_health ) {
health = max_health ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetYaw ( Event * ev )
{
ev - > AddFloat ( angles [ 1 ] ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetKillTarget ( const char * text )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
if ( text ) {
killtarget = text ;
} else {
killtarget = " " ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
const char * Entity : : getModel ( ) const
{
return gi . TIKI_NameForNum ( edict - > tiki ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : setModel ( const str & mdl )
2016-03-27 11:49:47 +02:00
{
2023-10-01 21:00:32 +02:00
int animnum ;
int i ;
if ( mdl ! = " " & & mdl [ 0 ] = = ' * ' ) {
model = mdl ;
gi . SetBrushModel ( edict , mdl ) ;
if ( ( edict - > solid = = SOLID_BSP ) & & ! edict - > s . modelindex ) {
const char * name ;
name = getClassID ( ) ;
if ( ! name ) {
name = getClassname ( ) ;
2023-08-09 23:09:09 +02:00
}
2023-10-01 21:00:32 +02:00
gi . DPrintf ( " %s with SOLID_BSP and no model - '%s'(%d) \n " , name , targetname . c_str ( ) , entnum ) ;
2023-08-09 23:09:09 +02:00
2023-10-01 21:00:32 +02:00
// Make it non-solid so that the collision code doesn't kick us out.
setSolidType ( SOLID_NOT ) ;
2023-08-09 23:09:09 +02:00
}
2023-10-01 21:00:32 +02:00
SetSize ( ) ;
return ;
2023-08-09 23:09:09 +02:00
}
model = CanonicalTikiName ( mdl ) ;
if ( ! setModel ( ) ) {
2023-08-10 23:06:03 +02:00
Com_Printf ( " ^~^~^ Bad model name '%s' \n " , mdl . c_str ( ) ) ;
2023-08-09 23:09:09 +02:00
return ;
}
mins = vec_zero ;
maxs = vec_zero ;
2023-10-01 21:00:32 +02:00
// make sure to clear all frame infos when switching models
// so the entity doesn't end up with 'broken' animations
for ( i = 0 ; i < MAX_FRAMEINFOS ; i + + ) {
ClearAnimSlot ( i ) ;
2023-08-09 23:09:09 +02:00
}
2023-10-01 21:00:32 +02:00
if ( mdl = = " " ) {
SetSize ( ) ;
2023-08-09 23:09:09 +02:00
return ;
}
2023-10-01 21:00:32 +02:00
// search for the default idle animation
animnum = gi . Anim_NumForName ( edict - > tiki , " idle " ) ;
if ( animnum < 0 ) {
animnum = 0 ;
2023-08-09 23:09:09 +02:00
}
2023-10-01 21:00:32 +02:00
// play the default idle animation
StartAnimSlot ( 0 , animnum , 1 ) ;
// process all TIKI init commands
2023-08-09 23:09:09 +02:00
ProcessInitCommands ( ) ;
2023-10-01 21:00:32 +02:00
SetSize ( ) ;
2023-08-09 23:09:09 +02:00
if ( edict - > tiki & & ! mins . length ( ) & & ! maxs . length ( ) ) {
vec3_t tempmins , tempmaxs ;
2023-09-27 23:21:34 +02:00
gi . TIKI_CalculateBounds ( edict - > tiki , edict - > s . scale , tempmins , tempmaxs ) ;
2023-08-09 23:09:09 +02:00
setSize ( tempmins , tempmaxs ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : setModel ( void )
{
level . skel_index [ edict - > s . number ] = - 1 ;
return gi . setmodel ( edict , model ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetSize ( void )
{
mins = edict - > r . mins ;
maxs = edict - > r . maxs ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
size = maxs - mins ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
edict - > r . radius = size . length ( ) * 0.5 ;
edict - > radius2 = edict - > r . radius * edict - > r . radius ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : ProcessInitCommands ( void )
{
dtikianim_t * a ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( LoadingSavegame ) {
// Don't process init commands when loading a savegame since
// it will cause items to be added to inventories unnecessarily.
// All variables affected by the init commands will be set
// by the unarchive functions.
//
// we do want to process the cache commands though regardless
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
a = edict - > tiki - > a ;
if ( a - > num_server_initcmds ) {
int i , j ;
Event * event ;
for ( i = 0 ; i < a - > num_server_initcmds ; i + + ) {
2023-10-01 21:00:32 +02:00
event = new Event ( a - > server_initcmds [ i ] . args [ 0 ] , a - > server_initcmds [ i ] . num_args ) ;
2023-08-09 23:09:09 +02:00
for ( j = 1 ; j < a - > server_initcmds [ i ] . num_args ; j + + ) {
event - > AddToken ( a - > server_initcmds [ i ] . args [ j ] ) ;
}
if ( ! ProcessEvent ( event ) ) {
Com_Printf (
" ^~^~^ Entity::ProcessInitCommands: Bad init server command '%s' in '%s' \n " ,
a - > server_initcmds [ i ] . args [ 0 ] ,
edict - > tiki - > name
) ;
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
}
}
}
void Entity : : EventHideModel ( Event * ev )
{
hideModel ( ) ;
}
void Entity : : EventShowModel ( Event * ev )
{
showModel ( ) ;
}
void Entity : : SetTeamEvent ( Event * ev )
{
moveteam = ev - > GetString ( 1 ) ;
}
void Entity : : TriggerEvent ( Event * ev )
{
const char * name ;
Event * event ;
Entity * ent ;
ConSimple * tlist ;
int i ;
int num ;
name = ev - > GetString ( 1 ) ;
// Check for object commands
if ( name & & name [ 0 ] = = ' $ ' ) {
str sName = str ( name + 1 ) ;
tlist = world - > GetTargetList ( sName ) ;
num = tlist - > NumObjects ( ) ;
for ( i = 1 ; i < = num ; i + + ) {
ent = ( Entity * ) tlist - > ObjectAt ( i ) . Pointer ( ) ;
assert ( ent ) ;
event = new Event ( EV_Activate ) ;
event - > AddEntity ( this ) ;
ent - > ProcessEvent ( event ) ;
}
} else if ( name [ 0 ] = = ' * ' ) // Check for entnum commands
{
if ( ! IsNumeric ( & name [ 1 ] ) ) {
gi . Printf ( " Expecting numeric value for * command, but found '%s' \n " , & name [ 1 ] ) ;
} else {
ent = G_GetEntity ( atoi ( & name [ 1 ] ) ) ;
if ( ent ) {
event = new Event ( EV_Activate ) ;
event - > AddEntity ( this ) ;
ent - > ProcessEvent ( event ) ;
} else {
gi . Printf ( " Entity not found for * command \n " ) ;
}
}
return ;
} else {
gi . Printf ( " Invalid entity reference '%s'. \n " , name ) ;
}
}
void Entity : : setAlpha ( float alpha )
{
if ( alpha > 1.0f ) {
alpha = 1.0f ;
}
if ( alpha < 0 ) {
alpha = 0 ;
}
edict - > s . alpha = alpha ;
}
void Entity : : setScale ( float scale )
{
edict - > s . scale = scale ;
}
void Entity : : setContentsSolid ( void )
{
setContents ( CONTENTS_BBOX ) ;
}
void Entity : : setSolidType ( solid_t type )
{
if ( ( ! LoadingSavegame ) & & ( type = = SOLID_BSP ) & & ( this ! = world )
& & ( ! model . length ( ) | | ( ( model [ 0 ] ! = ' * ' ) & & ( ! strstr ( model . c_str ( ) , " .bsp " ) ) ) ) ) {
gi . Printf (
" setSolidType " , " SOLID_BSP entity at x%.2f y%.2f z%.2f with no BSP model " , origin [ 0 ] , origin [ 1 ] , origin [ 2 ]
) ;
}
edict - > solid = type ;
//
// set the appropriate contents type
if ( edict - > solid = = SOLID_BBOX ) {
if ( ! getContents ( ) ) {
setContentsSolid ( ) ;
}
} else if ( edict - > solid = = SOLID_NOT ) {
if ( getContents ( )
& ( CONTENTS_CORPSE | CONTENTS_BODY | CONTENTS_UNKNOWN3 | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP
| CONTENTS_BBOX | CONTENTS_NOTTEAM2 | CONTENTS_NOTTEAM1 | CONTENTS_LADDER ) ) {
setContents ( 0 ) ;
}
} else if ( edict - > solid = = SOLID_BSP ) {
if ( ! getContents ( ) ) {
setContents ( CONTENTS_SOLID ) ;
}
}
link ( ) ;
}
void Entity : : setSize ( Vector min , Vector max )
{
Vector delta ;
if ( flags & FL_ROTATEDBOUNDS ) {
vec3_t tempmins , tempmaxs ;
//
// rotate the mins and maxs for the model
//
min . copyTo ( tempmins ) ;
max . copyTo ( tempmaxs ) ;
CalculateRotatedBounds2 ( edict - > mat , tempmins , tempmaxs ) ;
VectorCopy ( tempmins , edict - > r . mins ) ;
VectorCopy ( tempmaxs , edict - > r . maxs ) ;
SetSize ( ) ;
} else {
if ( ( min = = edict - > r . mins ) & & ( max = = edict - > r . maxs ) ) {
return ;
}
VectorCopy ( min , edict - > r . mins ) ;
VectorCopy ( max , edict - > r . maxs ) ;
SetSize ( ) ;
//
// get the full mins and maxs for this model
//
if ( edict - > tiki ) {
vec3_t fullmins , fullmaxs ;
Vector delta ;
2023-09-27 23:21:34 +02:00
gi . TIKI_CalculateBounds ( edict - > tiki , edict - > s . scale , fullmins , fullmaxs ) ;
2023-08-09 23:09:09 +02:00
delta = Vector ( fullmaxs ) - Vector ( fullmins ) ;
edict - > r . radius = delta . length ( ) * 0.5 ;
edict - > radius2 = edict - > r . radius * edict - > r . radius ;
}
}
link ( ) ;
}
Vector Entity : : getLocalVector ( Vector vec )
{
Vector pos ;
pos [ 0 ] = vec * orientation [ 0 ] ;
pos [ 1 ] = vec * orientation [ 1 ] ;
pos [ 2 ] = vec * orientation [ 2 ] ;
return pos ;
}
void Entity : : link ( void )
{
2023-08-15 01:27:35 +02:00
gi . linkentity ( edict ) ;
2023-08-09 23:09:09 +02:00
absmin = edict - > r . absmin ;
absmax = edict - > r . absmax ;
centroid = ( absmin + absmax ) * 0.5 ;
2023-08-29 00:03:07 +02:00
centroid . copyTo ( edict - > r . centroid ) ;
2023-08-09 23:09:09 +02:00
// If this has a parent, then set the areanum the same
// as the parent's
if ( edict - > s . parent ! = ENTITYNUM_NONE ) {
edict - > r . areanum = g_entities [ edict - > s . parent ] . r . areanum ;
}
}
void Entity : : addOrigin ( Vector add )
{
setLocalOrigin ( localorigin + add ) ;
}
void Entity : : setOrigin ( void )
{
Entity * ent ;
if ( edict - > s . parent = = ENTITYNUM_NONE ) {
setLocalOrigin ( localorigin ) ;
}
// If entity has a parent, then set the origin as the
// centroid of the parent, and set edict->s.netorigin
// as the local origin of the entity which will be used
// to position this entity on the client.
else {
Vector forward , left , up ;
VectorClear ( edict - > s . netorigin ) ;
ent = ( Entity * ) G_GetEntity ( edict - > s . parent ) ;
ent - > GetTag ( edict - > s . tag_num & TAG_MASK , & origin , & forward , & left , & up ) ;
origin + = edict - > s . attach_offset [ 0 ] * forward ;
origin + = edict - > s . attach_offset [ 1 ] * left ;
origin + = edict - > s . attach_offset [ 2 ] * up ;
localorigin = vec_zero ;
updateOrigin ( ) ;
}
}
void Entity : : updateOrigin ( void )
{
Entity * ent ;
int i , num ;
origin . copyTo ( edict - > s . origin ) ;
link ( ) ;
//
// go through and set our children
//
num = numchildren ;
for ( i = 0 ; ( i < MAX_MODEL_CHILDREN ) & & num ; i + + ) {
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
ent = ( Entity * ) G_GetEntity ( children [ i ] ) ;
ent - > setOrigin ( ) ;
num - - ;
}
for ( i = 0 ; i < m_iNumGlues ; i + + ) {
m_pGlues [ i ] - > setOrigin ( ) ;
}
}
void Entity : : setOrigin ( Vector org )
{
if ( m_pGlueMaster ) {
org = m_pGlueMaster - > origin ;
velocity = m_pGlueMaster - > velocity ;
}
if ( bindmaster ) {
origin = org ;
org - = bindmaster - > origin ;
if ( bind_use_my_angles ) {
MatrixTransformVectorRight ( orientation , org , localorigin ) ;
} else {
MatrixTransformVectorRight ( bindmaster - > orientation , org , localorigin ) ;
}
origin . copyTo ( edict - > s . netorigin ) ;
} else {
if ( edict - > s . parent ! = ENTITYNUM_NONE ) {
detach ( ) ;
}
origin = org ;
localorigin = org ;
origin . copyTo ( edict - > s . netorigin ) ;
}
updateOrigin ( ) ;
}
void Entity : : setOriginEvent ( Vector org )
{
velocity = vec_zero ;
setOrigin ( org ) ;
}
void Entity : : setLocalOrigin ( Vector org )
{
if ( m_pGlueMaster ) {
org = m_pGlueMaster - > origin ;
velocity = m_pGlueMaster - > velocity ;
}
if ( bindmaster ) {
localorigin = org ;
if ( bind_use_my_angles ) {
MatrixTransformVector ( localorigin , orientation , origin ) ;
} else {
MatrixTransformVector ( localorigin , bindmaster - > orientation , origin ) ;
}
origin + = bindmaster - > origin ;
origin . copyTo ( edict - > s . netorigin ) ;
} else {
origin = org ;
localorigin = org ;
origin . copyTo ( edict - > s . netorigin ) ;
}
updateOrigin ( ) ;
}
void Entity : : GetRawTag ( int tagnum , orientation_t * orient )
{
* orient = G_TIKI_Orientation ( edict , tagnum & TAG_MASK ) ;
}
qboolean Entity : : GetRawTag ( const char * name , orientation_t * orient )
{
int tagnum ;
tagnum = gi . Tag_NumForName ( edict - > tiki , name ) ;
if ( tagnum < 0 ) {
return false ;
}
GetRawTag ( tagnum , orient ) ;
return true ;
}
void Entity : : GetTag ( int tagnum , orientation_t * orient )
{
orientation_t o ;
int i ;
GetRawTag ( tagnum , & o ) ;
VectorCopy ( origin , orient - > origin ) ;
for ( i = 0 ; i < 3 ; i + + ) {
VectorMA ( orient - > origin , o . origin [ i ] , orientation [ i ] , orient - > origin ) ;
}
MatrixMultiply ( o . axis , orientation , orient - > axis ) ;
}
qboolean Entity : : GetTag ( const char * name , orientation_t * orient )
{
int tagnum ;
tagnum = gi . Tag_NumForName ( edict - > tiki , name ) ;
if ( tagnum < 0 ) {
return false ;
}
GetTag ( tagnum , orient ) ;
return true ;
}
void Entity : : GetTag ( int tagnum , Vector * pos , Vector * forward , Vector * left , Vector * up )
{
orientation_t orient ;
GetTag ( tagnum , & orient ) ;
if ( pos ) {
* pos = Vector ( orient . origin ) ;
}
if ( forward ) {
* forward = Vector ( orient . axis [ 0 ] ) ;
}
if ( left ) {
* left = Vector ( orient . axis [ 1 ] ) ;
}
if ( up ) {
* up = Vector ( orient . axis [ 2 ] ) ;
}
}
qboolean Entity : : GetTag ( const char * name , Vector * pos , Vector * forward , Vector * left , Vector * up )
{
int tagnum ;
tagnum = gi . Tag_NumForName ( edict - > tiki , name ) ;
if ( tagnum < 0 ) {
return false ;
}
GetTag ( tagnum , pos , forward , left , up ) ;
return true ;
}
int Entity : : CurrentAnim ( int slot ) const
{
return 0 ;
}
float Entity : : CurrentTime ( int slot ) const
{
return 0 ;
}
void Entity : : ClearAnimSlot ( int slot )
{
edict - > s . frameInfo [ slot ] . index = 0 ;
edict - > s . frameInfo [ slot ] . weight = 0 ;
edict - > s . frameInfo [ slot ] . time = 0 ;
}
void Entity : : StartAnimSlot ( int slot , int index , float weight )
{
edict - > s . frameInfo [ slot ] . index = index ;
edict - > s . frameInfo [ slot ] . weight = weight ;
edict - > s . frameInfo [ slot ] . time = 0 ;
}
void Entity : : RestartAnimSlot ( int slot )
{
edict - > s . frameInfo [ slot ] . time = 0 ;
}
void Entity : : addAngles ( Vector add )
{
if ( bindmaster ) {
setAngles ( localangles + add ) ;
} else {
setAngles ( angles + add ) ;
}
}
void Entity : : setAngles ( void )
{
if ( bindmaster ) {
setAngles ( localangles ) ;
} else {
setAngles ( angles ) ;
}
}
void Entity : : setAngles ( Vector ang )
{
Entity * ent ;
int num , i ;
if ( m_bGlueAngles & & m_pGlueMaster ) {
ang = m_pGlueMaster - > angles ;
avelocity = m_pGlueMaster - > avelocity ;
}
angles [ 0 ] = AngleMod ( ang [ 0 ] ) ;
angles [ 1 ] = AngleMod ( ang [ 1 ] ) ;
angles [ 2 ] = AngleMod ( ang [ 2 ] ) ;
localangles = angles ;
if ( bindmaster ) {
float mat [ 3 ] [ 3 ] ;
AnglesToAxis ( localangles , mat ) ;
R_ConcatRotations ( mat , bindmaster - > orientation , orientation ) ;
MatrixToEulerAngles ( orientation , angles ) ;
} else {
AnglesToAxis ( angles , orientation ) ;
}
angles . copyTo ( edict - > s . netangles ) ;
angles . copyTo ( edict - > s . angles ) ;
// Fill the edicts matrix
VectorCopy ( orientation [ 0 ] , edict - > mat [ 0 ] ) ;
VectorCopy ( orientation [ 1 ] , edict - > mat [ 1 ] ) ;
VectorCopy ( orientation [ 2 ] , edict - > mat [ 2 ] ) ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( edict - > s . eFlags & EF_LINKANGLES ) {
angles . copyTo ( edict - > r . currentAngles ) ;
link ( ) ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
//
// go through and set our children
//
num = numchildren ;
for ( i = 0 ; ( i < MAX_MODEL_CHILDREN ) & & num ; i + + ) {
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
ent = ( Entity * ) G_GetEntity ( children [ i ] ) ;
ent - > setAngles ( ) ;
num - - ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < m_iNumGlues ; i + + ) {
m_pGlues [ i ] - > setAngles ( ) ;
}
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : droptofloor ( float maxfall )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
trace_t trace ;
Vector end ;
Vector start ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
start = origin + Vector ( " 0 0 1 " ) ;
end = origin ;
end [ 2 ] - = maxfall ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
trace = G_Trace ( start , mins , maxs , end , this , edict - > clipmask , false , " Entity::droptofloor " ) ;
if ( trace . fraction = = 1 | | trace . startsolid | | trace . allsolid | | ! trace . ent ) {
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setOrigin ( trace . endpos ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : DamageType ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
str damage ;
damage = ev - > GetString ( 1 ) ;
if ( damage = = " all " ) {
damage_type = - 1 ;
} else {
2023-08-15 01:27:35 +02:00
damage_type = MOD_string_to_int ( damage ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Damage (
Entity * inflictor ,
Entity * attacker ,
float damage ,
Vector position ,
Vector direction ,
Vector normal ,
int knockback ,
int dflags ,
int meansofdeath ,
int location
)
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Event * ev ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// if our damage types do not match, return
if ( ! MOD_matches ( meansofdeath , damage_type ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! attacker ) {
attacker = world ;
}
if ( ! inflictor ) {
inflictor = world ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev = new Event ( EV_Damage ) ;
ev - > AddEntity ( attacker ) ;
ev - > AddFloat ( damage ) ;
ev - > AddEntity ( inflictor ) ;
ev - > AddVector ( position ) ;
ev - > AddVector ( direction ) ;
ev - > AddVector ( normal ) ;
ev - > AddInteger ( knockback ) ;
ev - > AddInteger ( dflags ) ;
ev - > AddInteger ( meansofdeath ) ;
ev - > AddInteger ( location ) ;
ProcessEvent ( ev ) ;
}
void Entity : : DamageEvent ( Event * ev )
{
Entity * inflictor ;
Entity * attacker ;
int damage ;
Vector dir ;
Vector momentum ;
Vector position , direction , normal ;
int knockback , damageflags , meansofdeath , location ;
Event * event ;
float m ;
2023-10-04 00:33:27 +02:00
EntityPtr This ;
2023-08-09 23:09:09 +02:00
2023-10-04 00:33:27 +02:00
// Use a safe pointer because it might be deleted in Unregister
This = this ;
if ( ( takedamage = = DAMAGE_NO ) | | ( movetype = = MOVETYPE_NOCLIP ) | | health < = 0 ) {
2023-08-09 23:09:09 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
attacker = ev - > GetEntity ( 1 ) ;
damage = ev - > GetInteger ( 2 ) ;
inflictor = ev - > GetEntity ( 3 ) ;
2023-10-04 00:33:27 +02:00
meansofdeath = ev - > GetInteger ( 9 ) ;
if ( Immune ( meansofdeath ) ) {
return ;
}
if ( ! attacker ) {
ScriptError ( " attacker is NULL " ) ;
return ;
}
if ( ! inflictor ) {
ScriptError ( " inflictor is NULL " ) ;
return ;
}
2023-08-09 23:09:09 +02:00
position = ev - > GetVector ( 4 ) ;
direction = ev - > GetVector ( 5 ) ;
normal = ev - > GetVector ( 6 ) ;
knockback = ev - > GetInteger ( 7 ) ;
damageflags = ev - > GetInteger ( 8 ) ;
location = ev - > GetInteger ( 10 ) ;
// figure momentum add
if ( ( inflictor ! = world ) & & ( movetype ! = MOVETYPE_NONE ) & & ( movetype ! = MOVETYPE_STATIONARY )
2023-10-04 00:33:27 +02:00
& & ( movetype ! = MOVETYPE_BOUNCE ) & & ( movetype ! = MOVETYPE_PUSH ) & & ( movetype ! = MOVETYPE_STOP )
& & ( movetype ! = MOVETYPE_VEHICLE ) ) {
2023-08-09 23:09:09 +02:00
dir = origin - ( inflictor - > origin + ( inflictor - > mins + inflictor - > maxs ) * 0.5 ) ;
dir . normalize ( ) ;
2023-10-04 00:33:27 +02:00
if ( mass < 20 ) {
m = 20 ;
2023-08-09 23:09:09 +02:00
} else {
m = mass ;
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:33:27 +02:00
momentum = dir * damage * ( 1000.0 / m ) ;
2023-08-09 23:09:09 +02:00
velocity + = momentum ;
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:33:27 +02:00
if ( ! deathmatch - > integer & & IsSubclassOfPlayer ( ) ) {
damage * = 0.15 ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:33:27 +02:00
// check for godmode or invincibility
if ( ! ( flags & FL_GODMODE ) ) {
// do the damage
health - = damage ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:33:27 +02:00
/*
2023-08-09 23:09:09 +02:00
if ( deadflag ) {
// Check for gib.
if ( inflictor - > IsSubclassOfProjectile ( ) ) {
Event * gibEv ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
health - = damage ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
gibEv = new Event ( EV_Gib ) ;
gibEv - > AddEntity ( this ) ;
gibEv - > AddFloat ( health ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ProcessEvent ( gibEv ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return ;
}
2023-10-04 00:33:27 +02:00
*/
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( health < = 0 ) {
if ( attacker ) {
event = new Event ( EV_GotKill ) ;
event - > AddEntity ( this ) ;
event - > AddInteger ( damage ) ;
event - > AddEntity ( inflictor ) ;
event - > AddInteger ( meansofdeath ) ;
event - > AddInteger ( 0 ) ;
attacker - > ProcessEvent ( event ) ;
}
2016-03-27 11:49:47 +02:00
2023-10-04 00:33:27 +02:00
if ( ! This ) {
return ;
}
2023-08-09 23:09:09 +02:00
event = new Event ( EV_Killed ) ;
event - > AddEntity ( attacker ) ;
event - > AddFloat ( damage ) ;
event - > AddEntity ( inflictor ) ;
event - > AddVector ( position ) ;
event - > AddVector ( direction ) ;
event - > AddVector ( normal ) ;
event - > AddInteger ( knockback ) ;
event - > AddInteger ( damageflags ) ;
event - > AddInteger ( meansofdeath ) ;
event - > AddInteger ( location ) ;
ProcessEvent ( event ) ;
2023-10-04 00:33:27 +02:00
if ( ! This ) {
return ;
}
// Notify scripts
Unregister ( STRING_DAMAGE ) ;
2023-08-09 23:09:09 +02:00
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
event = new Event ( EV_Pain ) ;
event - > AddEntity ( attacker ) ;
event - > AddFloat ( damage ) ;
event - > AddEntity ( inflictor ) ;
event - > AddVector ( position ) ;
event - > AddVector ( direction ) ;
event - > AddVector ( normal ) ;
event - > AddInteger ( knockback ) ;
event - > AddInteger ( damageflags ) ;
event - > AddInteger ( meansofdeath ) ;
event - > AddInteger ( location ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ProcessEvent ( event ) ;
2023-10-04 00:33:27 +02:00
if ( ! This ) {
return ;
}
// Notify scripts
Unregister ( STRING_DAMAGE ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
qboolean Entity : : IsTouching ( Entity * e1 )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
if ( e1 - > absmin . x > absmax . x ) {
return false ;
}
if ( e1 - > absmin . y > absmax . y ) {
return false ;
}
if ( e1 - > absmin . z > absmax . z ) {
return false ;
}
if ( e1 - > absmax . x < absmin . x ) {
return false ;
}
if ( e1 - > absmax . y < absmin . y ) {
return false ;
}
if ( e1 - > absmax . z < absmin . z ) {
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : IsInside ( Entity * e1 )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
return gi . HitEntity ( edict , e1 - > edict ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : FovCheck ( float * delta , float fovdot )
{
float deltadot = delta [ 0 ] * orientation [ 0 ] [ 0 ] + delta [ 1 ] * orientation [ 0 ] [ 1 ] ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( fovdot < 0.0f ) {
if ( deltadot > = 0.0f ) {
return true ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return ( delta [ 0 ] * delta [ 0 ] + delta [ 1 ] * delta [ 1 ] ) * fovdot * fovdot > ( deltadot * deltadot ) ;
} else {
if ( deltadot < 0.0f ) {
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return ( deltadot * deltadot ) > ( delta [ 0 ] * delta [ 0 ] + delta [ 1 ] * delta [ 1 ] ) * fovdot * fovdot ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
bool Entity : : CanSee ( Entity * ent , float fov , float vision_distance , bool bNoEnts )
2016-03-27 11:49:47 +02:00
{
2023-10-21 16:50:26 +02:00
vec2_t delta ;
int mask ;
VectorSub2D ( ent - > centroid , centroid , delta ) ;
2023-10-23 18:57:44 +02:00
if ( vision_distance > 0 & & Square ( vision_distance ) < VectorLength2DSquared ( delta ) ) {
2023-10-21 16:50:26 +02:00
return false ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-10-21 16:50:26 +02:00
if ( ! AreasConnected ( ent ) ) {
return false ;
}
if ( fov > 0 & & fov < 360 & & ! FovCheck ( delta , cos ( DEG2RAD ( fov / 2.f ) ) ) ) {
return false ;
}
if ( bNoEnts ) {
mask = MASK_CANSEE_NOENTS ;
} else {
mask = MASK_CANSEE ;
}
return G_SightTrace ( centroid , vec_zero , vec_zero , ent - > centroid , this , ent , mask , qfalse , " Sentient::CanSee " ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
bool Entity : : CanSee ( const Vector & org , float fov , float vision_distance , bool bNoEnts )
{
2023-10-21 16:50:26 +02:00
vec2_t delta ;
int mask ;
2016-03-27 11:49:47 +02:00
2023-10-21 16:50:26 +02:00
VectorSub2D ( org , centroid , delta ) ;
2023-08-09 23:09:09 +02:00
2023-10-23 18:57:44 +02:00
if ( vision_distance > 0 & & Square ( vision_distance ) < VectorLength2DSquared ( delta ) ) {
2023-10-21 16:50:26 +02:00
return false ;
}
if ( fov > 0 & & fov < 360 & & ! FovCheck ( delta , cos ( DEG2RAD ( fov / 2.f ) ) ) ) {
return false ;
}
if ( bNoEnts ) {
mask = MASK_CANSEE_NOENTS ;
} else {
mask = MASK_CANSEE ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-10-21 16:50:26 +02:00
return G_SightTrace ( centroid , vec_zero , vec_zero , org , this , NULL , mask , qfalse , " Sentient::CanSee " ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : FadeNoRemove ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float rate ;
float target ;
float myalpha ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
target = ev - > GetFloat ( 2 ) ;
} else {
target = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
rate = ev - > GetFloat ( 1 ) ;
assert ( rate ) ;
if ( rate > 0 ) {
rate = FRAMETIME / rate ;
}
} else {
rate = 0.03f ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
myalpha = edict - > s . alpha ;
myalpha - = rate ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( myalpha < target ) {
myalpha = target ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setAlpha ( myalpha ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( myalpha > target ) {
PostEvent ( * ev , FRAMETIME ) ;
}
G_SetConstantLight ( & edict - > s . constantLight , & myalpha , & myalpha , & myalpha , 0 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : FadeOut ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
float myscale ;
float myalpha ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
myscale = edict - > s . scale ;
myscale - = 0.03f ;
myalpha = edict - > s . alpha ;
myalpha - = 0.03f ;
if ( myscale < 0 ) {
myscale = 0 ;
}
if ( myalpha < 0 ) {
myalpha = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( myscale < = 0 & & myalpha < = 0 ) {
PostEvent ( EV_Remove , 0 ) ;
} else {
PostEvent ( * ev , FRAMETIME ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setScale ( myscale ) ;
setAlpha ( myalpha ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : FadeIn ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float rate ;
float target ;
float myalpha ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
target = ev - > GetFloat ( 2 ) ;
} else {
target = 1 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
rate = ev - > GetFloat ( 1 ) ;
assert ( rate ) ;
if ( rate > 0 ) {
rate = FRAMETIME / rate ;
}
} else {
rate = 0.03f ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
myalpha = edict - > s . alpha ;
myalpha + = rate ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( myalpha > target ) {
myalpha = target ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( myalpha < target ) {
PostEvent ( * ev , FRAMETIME ) ;
}
setAlpha ( myalpha ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Fade ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float rate ;
float target ;
float myalpha ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
target = ev - > GetFloat ( 2 ) ;
} else {
target = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
rate = ev - > GetFloat ( 1 ) ;
assert ( rate ) ;
if ( rate > 0 ) {
rate = FRAMETIME / rate ;
}
} else {
rate = 0.03f ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
myalpha = edict - > s . alpha ;
myalpha - = rate ;
if ( myalpha < = 0 ) {
PostEvent ( EV_Remove , 0 ) ;
return ;
}
if ( myalpha < target ) {
myalpha = target ;
}
if ( myalpha > target ) {
PostEvent ( * ev , FRAMETIME ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setAlpha ( myalpha ) ;
G_SetConstantLight ( & edict - > s . constantLight , & myalpha , & myalpha , & myalpha , 0 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Sink ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float rate ;
float target ;
float myalpha ;
Vector org ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
rate = 0.3f ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
target = ev - > GetFloat ( 2 ) ;
} else {
target = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
rate = ev - > GetFloat ( 1 ) ;
if ( rate > 0 ) {
rate / = level . frametime ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
myalpha = edict - > s . alpha - rate ;
if ( myalpha > 0 ) {
if ( myalpha < target ) {
myalpha = target ;
}
if ( target < myalpha ) {
2023-09-07 18:21:03 +02:00
Event * event = new Event ( std : : move ( * ev ) ) ;
2023-08-09 23:09:09 +02:00
PostEvent ( event , FRAMETIME ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setAlpha ( myalpha ) ;
org = origin ;
setOrigin ( org ) ;
Com_Printf ( " This is the sink?!? alpha: %f origin: %f %f %f \n " , myalpha , org . x , org . y , org . z ) ;
G_SetConstantLight ( & edict - > s . constantLight , & myalpha , & myalpha , & myalpha , NULL , NULL ) ;
edict - > s . alpha = myalpha ;
} else {
// No alpha, the entity can be immediately removed
PostEvent ( EV_Remove , 0 ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetMassEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
mass = ev - > GetFloat ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : CheckGround ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Vector point ;
trace_t trace ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( flags & ( FL_SWIM | FL_FLY ) ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( velocity . z > 100 ) {
groundentity = NULL ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// if the hull point one-quarter unit down is solid the entity is on ground
point = origin ;
point . z - = 0.25 ;
trace = G_Trace ( origin , mins , maxs , point , this , edict - > clipmask , false , " Entity::CheckGround " ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// check steepness
if ( ( trace . plane . normal [ 2 ] < = 0.7 ) & & ! trace . startsolid ) {
groundentity = NULL ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
groundentity = trace . ent ;
groundplane = trace . plane ;
groundcontents = trace . contents ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! trace . startsolid & & ! trace . allsolid ) {
setOrigin ( trace . endpos ) ;
velocity . z = 0 ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SafeSolid ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
trace_t trace ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setSolidType ( SOLID_NOT ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
trace = G_Trace ( origin , mins , maxs , origin , this , MASK_SAFESOLID , qfalse , " Entity::SafeSolid " ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ( trace . startsolid | | trace . allsolid ) & & trace . ent & & ( trace . ent - > entity - > IsSubclassOfSentient ( ) ) ) {
// Try again
PostEvent ( EV_SafeSolid , 0.5f ) ;
} else {
ProcessEvent ( EV_BecomeSolid ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : BecomeSolid ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( ( model . length ( ) ) & & ( ( model [ 0 ] = = ' * ' ) | | ( strstr ( model . c_str ( ) , " .bsp " ) ) ) ) {
setSolidType ( SOLID_BSP ) ;
} else {
setSolidType ( SOLID_BBOX ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : BecomeNonSolid ( Event * ev )
{
setSolidType ( SOLID_NOT ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : Ghost ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
// Make not solid, but send still send over whether it is hidden or not
setSolidType ( SOLID_NOT ) ;
edict - > r . svFlags & = ~ SVF_NOCLIENT ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LoopSound ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
str sound_name ;
float volume = DEFAULT_VOL ;
float min_dist = DEFAULT_MIN_DIST ;
str min_dist_string ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) < 1 ) {
return ;
}
2016-03-27 11:49:47 +02:00
2024-06-15 16:22:34 +02:00
if ( level . spawning ) {
// If the server is currently spawning
// repost the event as loopsound wouldn't work properly
// on the client
Event * newev = new Event ( * ev ) ;
PostEvent ( newev , level . frametime ) ;
return ;
}
2023-08-09 23:09:09 +02:00
// Get parameters
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
sound_name = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
volume = ev - > GetFloat ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
min_dist_string = ev - > GetString ( 3 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( min_dist_string = = LEVEL_WIDE_STRING ) {
min_dist = LEVEL_WIDE_MIN_DIST ;
} else {
min_dist = ev - > GetFloat ( 3 ) ;
}
}
// Add this sound to loop
LoopSound ( sound_name . c_str ( ) , volume , min_dist ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LoopSound ( str sound_name , float volume , float min_dist , float max_dist , float pitch )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
str name ;
str random_alias ;
AliasListNode_t * ret = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Get the real sound to be played
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( sound_name . length ( ) > 0 ) {
// Get the real sound to play
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
name = GetRandomAlias ( sound_name , & ret ) . c_str ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! name ) {
name = sound_name . c_str ( ) ;
}
2023-08-01 19:59:05 +02:00
2023-08-09 23:09:09 +02:00
if ( name . length ( ) & & ret ) {
int aliaschannel = ret - > channel ;
float aliasvolume = G_Random ( ) * ret - > volumeMod + ret - > volume ;
float aliasmin_dist = ret - > dist ;
float aliasmax_dist = ret - > maxDist ;
float aliaspitch = G_Random ( ) * ret - > pitchMod + ret - > pitch ;
int aliasstreamed = ret - > streamed ;
// Add the looping sound to the entity
edict - > s . loopSound = gi . soundindex ( name , aliasstreamed ) ;
2024-06-15 16:33:02 +02:00
edict - > s . loopSoundVolume = volume < 0 ? ( aliasvolume ) : ( aliasvolume * volume ) ;
edict - > s . loopSoundMinDist = min_dist < 0 ? ( aliasmin_dist ) : ( min_dist ) ;
edict - > s . loopSoundMaxDist = max_dist < 0 ? ( aliasmax_dist ) : ( max_dist ) ;
edict - > s . loopSoundPitch = pitch < 0 ? ( aliaspitch ) : ( aliaspitch * pitch ) ;
2023-08-09 23:09:09 +02:00
// Local sound will always be heard
edict - > s . loopSoundFlags = aliaschannel = = CHAN_LOCAL ;
} else {
gi . DPrintf (
" ERROR: Entity::LoopSound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix. \n " ,
sound_name . c_str ( )
) ;
}
}
2023-08-01 19:59:05 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : StopLoopSound ( Event * ev )
2023-08-01 19:59:05 +02:00
{
2023-08-09 23:09:09 +02:00
StopLoopSound ( ) ;
2023-08-01 19:59:05 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : StopLoopSound ( void )
2023-08-01 19:59:05 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > s . loopSound = 0 ;
2023-08-01 19:59:05 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : ProcessSoundEvent ( Event * ev , qboolean checkSubtitle )
2023-08-01 19:59:05 +02:00
{
2023-08-09 23:09:09 +02:00
str sound_name ;
str wait ;
2024-08-26 00:45:25 +02:00
bool waitTillDone = false ;
2023-08-09 23:09:09 +02:00
float volume ;
int channel = 0 ;
2023-08-01 19:59:05 +02:00
2023-08-09 23:09:09 +02:00
// Set defaults
volume = DEFAULT_VOL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 3 ) {
Com_Printf ( " ERROR Sound. Format is playsound soundname <wait> \n " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Get sound parameters
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
sound_name = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
wait = ev - > GetString ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2024-08-26 00:45:25 +02:00
if ( ! Q_stricmp ( wait . c_str ( ) , " wait " ) ) {
waitTillDone = true ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) = = 3 ) {
volume = ev - > GetFloat ( 3 ) ;
}
2024-08-26 00:45:25 +02:00
} else if ( ! Q_stricmp ( wait . c_str ( ) , " volume " ) ) {
if ( ev - > NumArgs ( ) ! = 3 ) {
ScriptError ( " Entity::Sound: volume not followed by a float " ) ;
}
volume = ev - > GetFloat ( 3 ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( volume = = DEFAULT_VOL ) {
2024-08-26 00:45:25 +02:00
Sound ( sound_name , CHAN_AUTO , volume , 0 , NULL , 0 , 0 , waitTillDone , checkSubtitle , - 1.0f ) ;
2023-08-09 23:09:09 +02:00
} else {
2024-08-26 00:45:25 +02:00
Sound ( sound_name , - 1 , volume , - 1.0f , NULL , - 1.0f , 1 , waitTillDone , checkSubtitle , - 1.0f ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Sound ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( level . spawning ) {
Event * event = new Event ( EV_Sound ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( int i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
event - > AddValue ( ev - > GetValue ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
PostEvent ( event , level . frametime ) ;
} else {
ProcessSoundEvent ( ev , true ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : StopSound ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
if ( ev - > NumArgs ( ) < 1 ) {
StopSound ( CHAN_BODY ) ;
} else {
StopSound ( ev - > GetInteger ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : StopSound ( int channel )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
gi . StopSound ( entnum , channel ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetLight ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
float r , g , b ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) = = 1 ) {
Vector tmp ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tmp = ev - > GetVector ( 1 ) ;
r = tmp . x ;
g = tmp . y ;
b = tmp . z ;
} else {
r = ev - > GetFloat ( 1 ) ;
g = ev - > GetFloat ( 2 ) ;
b = ev - > GetFloat ( 3 ) ;
lightRadius = ev - > GetFloat ( 4 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
G_SetConstantLight ( & edict - > s . constantLight , & r , & g , & b , & lightRadius ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LightOn ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
G_SetConstantLight ( & edict - > s . constantLight , NULL , NULL , NULL , & lightRadius ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LightOff ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float radius = 0 ;
G_SetConstantLight ( & edict - > s . constantLight , NULL , NULL , NULL , & radius ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LightRed ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float r ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
r = ev - > GetFloat ( 1 ) ;
G_SetConstantLight ( & edict - > s . constantLight , & r , NULL , NULL , NULL ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : LightGreen ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
float g ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
g = ev - > GetFloat ( 1 ) ;
G_SetConstantLight ( & edict - > s . constantLight , NULL , & g , NULL , NULL ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : LightBlue ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
float b ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
b = ev - > GetFloat ( 1 ) ;
G_SetConstantLight ( & edict - > s . constantLight , NULL , NULL , & b , NULL ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : LightRadius ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
lightRadius = ev - > GetFloat ( 1 ) ;
G_SetConstantLight ( & edict - > s . constantLight , NULL , NULL , NULL , & lightRadius ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : LightStyle ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
int style ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
style = ev - > GetInteger ( 1 ) ;
G_SetConstantLight ( & edict - > s . constantLight , NULL , NULL , NULL , NULL , & style ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetSize ( Event * ev )
{
Vector min , max ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
min = ev - > GetVector ( 1 ) ;
max = ev - > GetVector ( 2 ) ;
setSize ( min , max ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetMins ( Event * ev )
{
Vector min ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
min = ev - > GetVector ( 1 ) ;
setSize ( min , maxs ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetMaxs ( Event * ev )
{
Vector max ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
max = ev - > GetVector ( 1 ) ;
setSize ( mins , max ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetMins ( Event * ev )
{
ev - > AddVector ( mins ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetMaxs ( Event * ev )
{
ev - > AddVector ( maxs ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetScale ( Event * ev )
{
setScale ( ev - > GetFloat ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetScale ( Event * ev )
{
ev - > AddFloat ( edict - > s . scale ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetAlpha ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
setAlpha ( ev - > GetFloat ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetKillTarget ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
SetKillTarget ( ev - > GetString ( 1 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
Vector Entity : : GetControllerAngles ( int num )
{
Vector controller_angles ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
assert ( ( num > = 0 ) & & ( num < NUM_BONE_CONTROLLERS ) ) ;
if ( ( num < 0 ) | | ( num > = NUM_BONE_CONTROLLERS ) ) {
gi . Printf ( " GetControllerAngles " , " Bone controller index out of range (%d) \n " , num ) ;
return vec_zero ;
}
controller_angles = edict - > s . bone_angles [ num ] ;
return controller_angles ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetControllerAngles ( int num , vec3_t angles )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
assert ( ( num > = 0 ) & & ( num < NUM_BONE_CONTROLLERS ) ) ;
if ( ( num < 0 ) | | ( num > = NUM_BONE_CONTROLLERS ) ) {
gi . Printf ( " SetControllerAngles " , " Bone controller index out of range (%d) \n " , num ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
VectorCopy ( angles , edict - > s . bone_angles [ num ] ) ;
EulerToQuat ( edict - > s . bone_angles [ num ] , edict - > s . bone_quat [ num ] ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetControllerAngles ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int num ;
Vector angles ;
num = ev - > GetInteger ( 1 ) ;
angles = ev - > GetVector ( 2 ) ;
// this check is missing in mohaa
if ( ( num < 0 ) | | ( num > = NUM_BONE_CONTROLLERS ) ) {
ScriptError ( " Bone controller index out of range. Index must be between 0- " STRING ( NUM_BONE_CONTROLLERS - 1 ) " . "
) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
VectorCopy ( angles , edict - > s . bone_angles [ num ] ) ;
EulerToQuat ( edict - > s . bone_angles [ num ] , edict - > s . bone_quat [ num ] ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : GetControllerAngles ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int num = ev - > GetInteger ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// this check is missing in mohaa
if ( ( num < 0 ) | | ( num > = NUM_BONE_CONTROLLERS ) ) {
ScriptError ( " Bone controller index out of range. Index must be between 0- " STRING ( NUM_BONE_CONTROLLERS - 1 ) " . "
) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddVector ( edict - > s . bone_angles [ num ] ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetControllerTag ( int num , int tag_num )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
assert ( ( num > = 0 ) & & ( num < NUM_BONE_CONTROLLERS ) ) ;
if ( ( num < 0 ) | | ( num > = NUM_BONE_CONTROLLERS ) ) {
gi . Printf ( " SetControllerTag " , " Bone controller index out of range (%d) \n " , num ) ;
return ;
}
edict - > s . bone_tag [ num ] = tag_num ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Sound (
str sound_name ,
int channel ,
float volume ,
float min_dist ,
Vector * sound_origin ,
float pitch ,
int argstype ,
int doCallback ,
int checkSubtitle ,
float max_dist
)
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
const char * name = NULL ;
vec3_t org ;
str random_alias ;
AliasListNode_t * ret = NULL ;
static cvar_t * g_subtitle = NULL ;
static bool _tmp = false ;
int num ;
2024-07-02 19:10:48 +02:00
int aliaschannel ;
float aliasvolume ;
float aliasmin_dist ;
float aliasmax_dist ;
float aliaspitch ;
2023-08-09 23:09:09 +02:00
if ( ! _tmp ) {
g_subtitle = gi . Cvar_Get ( " g_subtitle " , " 0 " , CVAR_ARCHIVE ) ;
_tmp = true ;
}
if ( doCallback & & g_gametype - > integer ) {
Com_Printf ( " ^~^~^ Callback of sound '%s' ignored. \n " , sound_name . c_str ( ) ) ;
doCallback = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( sound_name . length ( ) > 0 ) {
// Get the real sound to play
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
random_alias = GetRandomAlias ( sound_name , & ret ) . c_str ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( random_alias . length ( ) > 0 ) {
name = random_alias . c_str ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! name ) {
name = sound_name . c_str ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Play the sound
if ( name ! = NULL ) {
if ( ret ) {
2024-07-02 19:10:48 +02:00
aliaschannel = ret - > channel ;
aliasvolume = G_Random ( ) * ret - > volumeMod + ret - > volume ;
aliaspitch = G_Random ( ) * ret - > pitchMod + ret - > pitch ;
aliasmin_dist = ret - > dist ;
aliasmax_dist = ret - > maxDist ;
2023-08-09 23:09:09 +02:00
if ( channel < 0 ) {
channel = ret - > channel ;
}
num = entnum ;
if ( sound_origin ) {
VectorCopy ( * sound_origin , org ) ;
num = ENTITYNUM_NONE ;
} else {
VectorCopy ( edict - > s . origin , org ) ;
if ( doCallback ) {
2023-08-13 20:19:51 +02:00
num | = S_FLAG_DO_CALLBACK ;
2023-08-09 23:09:09 +02:00
}
}
2024-07-02 19:10:48 +02:00
switch ( argstype ) {
case 0 :
volume = aliasvolume ;
pitch = aliaspitch ;
min_dist = aliasmin_dist ;
max_dist = aliasmax_dist ;
channel = aliaschannel ;
break ;
case 1 :
2023-08-09 23:09:09 +02:00
if ( volume > = 0.0f ) {
2024-07-02 19:10:48 +02:00
volume = volume * aliasvolume ;
2023-08-09 23:09:09 +02:00
} else {
2024-07-02 19:10:48 +02:00
volume = aliasvolume ;
2023-08-09 23:09:09 +02:00
}
if ( pitch > = 0.0f ) {
2024-07-02 19:10:48 +02:00
pitch = pitch * aliaspitch ;
2023-08-09 23:09:09 +02:00
} else {
2024-07-02 19:10:48 +02:00
pitch = aliaspitch ;
2023-08-09 23:09:09 +02:00
}
if ( min_dist < 0.0f ) {
2024-07-02 19:10:48 +02:00
min_dist = aliasmin_dist ;
2023-08-09 23:09:09 +02:00
}
if ( max_dist < 0.0f ) {
2024-07-02 19:10:48 +02:00
max_dist = aliasmax_dist ;
}
if ( channel < 0 ) {
channel = aliaschannel ;
}
break ;
default :
if ( volume < 0.0 ) {
volume = aliasvolume ;
}
if ( pitch < 0.0 ) {
pitch = aliaspitch ;
}
if ( min_dist < 0.0 ) {
min_dist = aliasmin_dist ;
}
if ( max_dist < 0.0 ) {
max_dist = aliasmax_dist ;
}
if ( channel < 0 ) {
channel = aliaschannel ;
2023-08-09 23:09:09 +02:00
}
2024-07-02 19:10:48 +02:00
break ;
2023-08-09 23:09:09 +02:00
}
2024-07-02 19:10:48 +02:00
if ( ( ! checkSubtitle | | g_subtitle - > integer ) & & ret - > subtitle ) {
2023-08-09 23:09:09 +02:00
Entity * p = G_GetEntity ( 0 ) ;
2024-07-02 19:10:48 +02:00
if ( g_subtitle - > integer = = 2 | | Square ( max_dist ) > DistanceSquared ( org , p - > edict - > s . origin ) ) {
2023-08-09 23:09:09 +02:00
cvar_t * curSubtitle = gi . Cvar_Get ( " curSubtitle " , " 0 " , 0 ) ;
2024-07-02 19:10:48 +02:00
int curSub ;
2023-08-09 23:09:09 +02:00
2023-08-15 01:27:35 +02:00
gi . cvar_set ( va ( " subtitle%d " , curSubtitle - > integer ) , va ( " %s " , ret - > subtitle ) ) ;
2024-07-02 19:10:48 +02:00
curSub = curSubtitle - > integer + 1 ;
if ( curSubtitle - > integer + 1 < 0 ) {
curSub = curSubtitle - > integer + MAX_SUBTITLES ;
}
gi . cvar_set ( " curSubtitle " , va ( " %d " , ( curSubtitle - > integer + 1 ) - MAX_SUBTITLES * ( curSub > > 2 ) ) ) ;
2023-08-09 23:09:09 +02:00
}
}
gi . Sound ( & org , num , channel , name , volume , min_dist , pitch , max_dist , ret - > streamed ) ;
}
} else {
gi . DPrintf (
" ERROR: Entity::Sound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix. \n " ,
sound_name . c_str ( )
) ;
}
} else {
warning ( " Sound " , " Null sample pointer " ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : attach ( int parent_entity_num , int tag_num , qboolean use_angles , Vector offset )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
Entity * parent ;
if ( entnum = = parent_entity_num ) {
warning ( " attach " , " Trying to attach to oneself. " ) ;
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( edict - > s . parent ! = ENTITYNUM_NONE ) {
detach ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//
// make sure this is a modelanim entity so that the attach works properly
//
if ( edict - > s . eType = = ET_GENERAL ) {
edict - > s . eType = ET_MODELANIM ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//
// get the parent
//
parent = ( Entity * ) G_GetEntity ( parent_entity_num ) ;
if ( parent - > numchildren < MAX_MODEL_CHILDREN ) {
//
// find a free spot in the parent
//
for ( i = 0 ; i < MAX_MODEL_CHILDREN ; i + + ) {
if ( parent - > children [ i ] = = ENTITYNUM_NONE ) {
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
edict - > s . parent = parent_entity_num ;
setSolidType ( SOLID_NOT ) ;
parent - > children [ i ] = entnum ;
parent - > numchildren + + ;
edict - > s . tag_num = tag_num ;
edict - > s . attach_use_angles = use_angles ;
offset . copyTo ( edict - > s . attach_offset ) ;
setOrigin ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return true ;
}
return false ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : KillAttach ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
Entity * child = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Kill all of this entities children
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < MAX_MODEL_CHILDREN ; i + + ) {
if ( children [ i ] ! = ENTITYNUM_NONE ) {
// Remove child
child = ( Entity * ) G_GetEntity ( children [ i ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( child ) {
child - > ProcessEvent ( EV_Remove ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Remove child from this entity
children [ i ] = ENTITYNUM_NONE ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
numchildren = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : detach ( void )
{
int i ;
int num ;
Entity * parent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( edict - > s . parent = = ENTITYNUM_NONE ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
parent = ( Entity * ) G_GetEntity ( edict - > s . parent ) ;
if ( ! parent ) {
return ;
}
for ( i = 0 , num = parent - > numchildren ; i < MAX_MODEL_CHILDREN ; i + + ) {
if ( parent - > children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
if ( parent - > children [ i ] = = entnum ) {
parent - > children [ i ] = ENTITYNUM_NONE ;
parent - > numchildren - - ;
break ;
}
num - - ;
if ( ! num ) {
break ;
}
}
edict - > s . parent = ENTITYNUM_NONE ;
setOrigin ( origin ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Flags ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
const char * flag ;
int mask ;
int action ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
action = FLAG_IGNORE ;
flag = ev - > GetString ( i ) ;
switch ( flag [ 0 ] ) {
case ' + ' :
action = FLAG_ADD ;
flag + + ;
break ;
case ' - ' :
action = FLAG_CLEAR ;
flag + + ;
break ;
default :
gi . Printf ( " Entity::Flags " , " First character is not '+' or '-', assuming '+' \n " ) ;
action = FLAG_ADD ;
break ;
}
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( flag , " blood " ) ) {
mask = FL_BLOOD ;
} else if ( ! Q_stricmp ( flag , " explode " ) ) {
mask = FL_DIE_EXPLODE ;
} else if ( ! Q_stricmp ( flag , " die_gibs " ) ) {
mask = FL_DIE_GIBS ;
} else if ( ! Q_stricmp ( flag , " autoaim " ) ) {
mask = FL_AUTOAIM ;
} else if ( ! Q_stricmp ( flag , " god " ) ) {
mask = FL_GODMODE ;
} else {
mask = 0 ;
action = FLAG_IGNORE ;
gi . Printf ( " Unknown flag '%s' " , flag ) ;
}
switch ( action ) {
case FLAG_ADD :
flags | = mask ;
break ;
case FLAG_CLEAR :
flags & = ~ mask ;
break ;
case FLAG_IGNORE :
break ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Effects ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
const char * flag ;
int mask = 0 ;
int action ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
action = 0 ;
flag = ev - > GetString ( i ) ;
switch ( flag [ 0 ] ) {
case ' + ' :
action = FLAG_ADD ;
flag + + ;
break ;
case ' - ' :
action = FLAG_CLEAR ;
flag + + ;
break ;
default :
gi . Printf ( " Entity::Effects " , " First character is not '+' or '-', assuming '+' \n " ) ;
action = FLAG_ADD ;
break ;
}
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( flag , " everyframe " ) ) {
mask = EF_EVERYFRAME ;
}
if ( ! Q_stricmp ( flag , " antisbjuice " ) ) {
mask = EF_ANTISBJUICE ;
} else {
action = FLAG_IGNORE ;
gi . Printf ( " Unknown token %s. " , flag ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
switch ( action ) {
case FLAG_ADD :
edict - > s . eFlags | = mask ;
break ;
case FLAG_CLEAR :
edict - > s . eFlags & = ~ mask ;
break ;
case FLAG_IGNORE :
break ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : RenderEffects ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
const char * flag ;
int mask = 0 ;
int action ;
int i ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
action = 0 ;
flag = ev - > GetString ( i ) ;
switch ( flag [ 0 ] ) {
case ' + ' :
action = FLAG_ADD ;
flag + + ;
break ;
case ' - ' :
action = FLAG_CLEAR ;
flag + + ;
break ;
default :
gi . Printf ( " Entity::RenderEffects " , " First character is not '+' or '-', assuming '+' \n " ) ;
action = FLAG_ADD ;
break ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( flag , " dontdraw " ) ) {
mask = RF_DONTDRAW ;
} else if ( ! Q_stricmp ( flag , " betterlighting " ) ) {
mask = RF_EXTRALIGHT ;
} else if ( ! Q_stricmp ( flag , " lensflare " ) ) {
mask = RF_LENSFLARE ;
} else if ( ! Q_stricmp ( flag , " viewlensflare " ) ) {
mask = RF_VIEWLENSFLARE ;
} else if ( ! Q_stricmp ( flag , " lightoffset " ) ) {
mask = RF_LIGHTOFFSET ;
} else if ( ! Q_stricmp ( flag , " skyorigin " ) ) {
mask = RF_SKYORIGIN ;
} else if ( ! Q_stricmp ( flag , " fullbright " ) ) {
mask = RF_FULLBRIGHT ;
} else if ( ! Q_stricmp ( flag , " minlight " ) ) {
mask = RF_MINLIGHT ;
} else if ( ! Q_stricmp ( flag , " additivedynamiclight " ) ) {
mask = RF_ADDITIVE_DLIGHT ;
} else if ( ! Q_stricmp ( flag , " lightstyledynamiclight " ) ) {
mask = RF_LIGHTSTYLE_DLIGHT ;
} else if ( ! Q_stricmp ( flag , " shadow " ) ) {
mask = RF_SHADOW ;
} else if ( ! Q_stricmp ( flag , " preciseshadow " ) ) {
mask = RF_SHADOW_PRECISE ;
} else if ( ! Q_stricmp ( flag , " invisible " ) ) {
mask = RF_INVISIBLE ;
} else {
action = FLAG_IGNORE ;
gi . Printf ( " Unknown token %s. " , flag ) ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
switch ( action ) {
case FLAG_ADD :
edict - > s . renderfx | = mask ;
break ;
case FLAG_CLEAR :
edict - > s . renderfx & = ~ mask ;
break ;
case FLAG_IGNORE :
break ;
}
}
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SVFlags ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
const char * flag ;
int mask = 0 ;
Entity * ent = NULL ;
int singleClient = 0 ;
int action ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = ev - > NumArgs ( ) ; i + + ) {
action = 0 ;
flag = ev - > GetString ( i ) ;
switch ( flag [ 0 ] ) {
case ' + ' :
action = FLAG_ADD ;
flag + + ;
break ;
case ' - ' :
action = FLAG_CLEAR ;
flag + + ;
break ;
default :
gi . Printf ( " Entity::SVFlags: First character is not '+' or '-', assuming '+' \n " ) ;
action = FLAG_ADD ;
break ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( flag , " broadcast " ) ) {
mask = SVF_BROADCAST ;
} else if ( ! Q_stricmp ( flag , " sendonce " ) ) {
mask = SVF_SENDONCE ;
} else if ( ! Q_stricmp ( flag , " singleclient " ) ) {
mask = SVF_SINGLECLIENT ;
if ( action = = FLAG_ADD ) {
ent = ev - > GetEntity ( i + 1 ) ;
if ( ! ent ) {
ScriptError ( " No player specified for +singleclient! " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
i + + ;
} else if ( ! Q_stricmp ( flag , " notsingleclient " ) ) {
mask = SVF_NOTSINGLECLIENT ;
if ( action = = FLAG_ADD ) {
ent = ev - > GetEntity ( i + 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ent ) {
ScriptError ( " No player specified for +notsingleclient! " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
i + + ;
} else {
action = FLAG_IGNORE ;
gi . Printf ( " Entity::SVFlags: Unknown token %s. \n " , flag ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
switch ( action ) {
case FLAG_ADD :
edict - > r . svFlags | = mask ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ( mask & SVF_SINGLECLIENT ) | | ( mask & SVF_NOTSINGLECLIENT ) ) {
edict - > r . singleClient = singleClient ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
break ;
case FLAG_CLEAR :
edict - > r . svFlags & = ~ mask ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ( mask & SVF_SINGLECLIENT ) | | ( mask & SVF_NOTSINGLECLIENT ) ) {
edict - > r . singleClient = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
break ;
case FLAG_IGNORE :
break ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( edict - > r . svFlags & SVF_SENDONCE ) {
// Turn this entity into an event if the SENDONCE flag is sent
edict - > s . eType = ET_EVENTS ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : BroadcastAIEvent ( int iType , float rad )
2016-03-27 11:49:47 +02:00
{
2023-11-05 20:58:25 +01:00
if ( flags & FL_NOTARGET ) {
return ;
}
2024-08-28 00:40:57 +02:00
G_BroadcastAIEvent ( this , centroid , iType , rad ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : BroadcastAIEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int iType ;
float rad ;
str sTypeName ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ( this - > flags & FL_NOTARGET ) ) {
iType = AI_EVENT_MISC ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
sTypeName = ev - > GetString ( 1 ) ;
iType = G_AIEventTypeFromString ( sTypeName ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
rad = ev - > NumArgs ( ) < = 1 ? G_AIEventRadius ( iType ) : ev - > GetFloat ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
BroadcastAIEvent ( iType , rad ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : Think ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetWaterType ( void )
{
qboolean isinwater ;
2016-03-27 11:49:47 +02:00
2023-08-15 01:27:35 +02:00
watertype = gi . pointcontents ( origin , 0 ) ;
2023-08-09 23:09:09 +02:00
isinwater = watertype & MASK_WATER ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( isinwater ) {
waterlevel = 1 ;
} else {
waterlevel = 0 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DamageSkin ( trace_t * trace , float damage )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
/* FIXME : Do we need damage skins?
int surface ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// FIXME handle different bodyparts
surface = trace - > intersect . surface ;
if ( ! edict - > s . surfaces [ surface ] )
{
edict - > s . surfaces [ surface ] + + ;
}
*/
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : Kill ( Event * ev )
{
health = 0 ;
Damage ( this , this , 10 , origin , vec_zero , vec_zero , 0 , 0 , MOD_SUICIDE ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : Killed ( Event * ev )
{
deadflag = DEAD_DEAD ;
if ( health > 0 ) {
health = 0 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SurfaceCommand ( const char * surf_name , const char * token )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
const char * current_surface_name ;
int surface_num ;
int mask ;
int action ;
qboolean do_all = false ;
qboolean mult = false ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( surf_name [ strlen ( surf_name ) - 1 ] = = ' * ' ) {
mult = true ;
surface_num = 0 ;
} else if ( str ( surf_name ) ! = str ( " all " ) ) {
surface_num = gi . Surface_NameToNum ( edict - > tiki , surf_name ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( surface_num < 0 ) {
warning ( " SurfaceCommand " , " group %s not found. " , surf_name ) ;
return ;
}
} else {
surface_num = 0 ;
do_all = true ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
action = 0 ;
switch ( token [ 0 ] ) {
case ' + ' :
action = FLAG_ADD ;
token + + ;
break ;
case ' - ' :
action = FLAG_CLEAR ;
token + + ;
break ;
default :
warning ( " Entity::SurfaceModelEvent " , " First character is not '+' or '-', assuming '+' \n " ) ;
action = FLAG_ADD ;
break ;
}
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( token , " skin1 " ) ) {
mask = MDL_SURFACE_SKINOFFSET_BIT0 ;
} else if ( ! Q_stricmp ( token , " skin2 " ) ) {
mask = MDL_SURFACE_SKINOFFSET_BIT1 ;
} else if ( ! Q_stricmp ( token , " nodraw " ) ) {
mask = MDL_SURFACE_NODRAW ;
} else if ( ! Q_stricmp ( token , " crossfade " ) ) {
mask = MDL_SURFACE_CROSSFADE_SKINS ;
} else {
mask = 0 ;
warning ( " SurfaceCommand " , " Unknown token %s. " , token ) ;
action = FLAG_IGNORE ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
int numsurfaces ;
if ( edict - > tiki ) {
2023-09-27 23:21:34 +02:00
numsurfaces = gi . TIKI_NumSurfaces ( edict - > tiki ) ;
2023-08-09 23:09:09 +02:00
} else {
numsurfaces = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( ; surface_num < numsurfaces ; surface_num + + ) {
if ( mult ) {
current_surface_name = gi . Surface_NumToName ( edict - > tiki , surface_num ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( Q_stricmpn ( current_surface_name , surf_name , strlen ( surf_name ) - 1 ) ! = 0 ) {
continue ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
switch ( action ) {
case FLAG_ADD :
edict - > s . surfaces [ surface_num ] | = mask ;
break ;
case FLAG_CLEAR :
edict - > s . surfaces [ surface_num ] & = ~ mask ;
break ;
case FLAG_IGNORE :
break ;
}
if ( ! do_all & & ! mult ) {
break ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SurfaceModelEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-10-06 20:13:21 +02:00
str surf_name ;
str token ;
int i ;
2023-08-09 23:09:09 +02:00
surf_name = ev - > GetString ( 1 ) ;
for ( i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
token = ev - > GetString ( i ) ;
SurfaceCommand ( surf_name , token ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : AttachEvent ( Event * ev )
{
Entity * parent ;
2023-10-06 20:13:21 +02:00
str bone ;
2023-08-09 23:09:09 +02:00
int tagnum ;
qboolean use_angles = qtrue ;
Vector offset ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
parent = ev - > GetEntity ( 1 ) ;
bone = ev - > GetString ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
use_angles = ev - > GetInteger ( 3 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 3 ) {
offset = ev - > GetVector ( 4 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! parent ) {
return ;
}
tagnum = gi . Tag_NumForName ( parent - > edict - > tiki , bone ) ;
if ( tagnum > = 0 ) {
attach ( parent - > entnum , tagnum , use_angles , offset ) ;
} else {
2023-10-07 23:50:16 +02:00
warning ( " AttachEvent " , " Tag %s not found " , bone . c_str ( ) ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : AttachModelEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Animate * obj ;
2023-10-06 20:13:21 +02:00
str bone ;
2023-08-09 23:09:09 +02:00
str modelname ;
int tagnum ;
float remove_time , fade_time , fade_delay ;
Vector offset ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
obj = new Animate ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
modelname = ev - > GetString ( 1 ) ;
bone = ev - > GetString ( 2 ) ;
if ( ev - > NumArgs ( ) > 2 ) {
obj - > setScale ( ev - > GetFloat ( 3 ) ) ;
}
if ( ev - > NumArgs ( ) > 3 ) {
obj - > SetTargetName ( ev - > GetString ( 4 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 4 ) {
obj - > detach_at_death = ev - > GetInteger ( 5 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 5 ) {
remove_time = ev - > GetFloat ( 6 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( remove_time ! = - 1 ) {
Event * remove_event = new Event ( EV_Remove ) ;
obj - > PostEvent ( remove_event , remove_time ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 6 ) {
Event * fade_event ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
fade_time = ev - > GetFloat ( 7 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( fade_time ! = - 1 ) {
obj - > setAlpha ( 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
fade_event = new Event ( EV_FadeIn ) ;
fade_event - > AddFloat ( fade_time ) ;
obj - > PostEvent ( fade_event , 0 ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 7 ) {
Event * fade_event ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
fade_delay = ev - > GetFloat ( 8 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( fade_delay ! = - 1 ) {
if ( ev - > NumArgs ( ) > 8 ) {
fade_time = ev - > GetFloat ( 9 ) ;
} else {
fade_time = 0 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
fade_event = new Event ( EV_Fade ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( fade_time ) {
fade_event - > AddFloat ( fade_time ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
obj - > PostEvent ( fade_event , fade_delay ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 9 ) {
offset = ev - > GetVector ( 10 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
obj - > setModel ( modelname ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tagnum = gi . Tag_NumForName ( edict - > tiki , bone ) ;
if ( tagnum > = 0 ) {
if ( obj - > attach ( this - > entnum , tagnum , true , offset ) ) {
obj - > NewAnim ( " idle " ) ;
} else {
2024-02-04 16:30:22 +01:00
warning ( " AttachModelEvent " , " Could not attach model %s to tag \" %s \" on entnum #%d (targetname = %s) " , modelname . c_str ( ) , bone . c_str ( ) , entnum , targetname . c_str ( ) ) ;
if ( g_iInThinks ) {
PostEvent ( EV_Remove , 0 ) ;
} else {
delete obj ;
}
2023-08-09 23:09:09 +02:00
return ;
}
} else {
2023-10-07 23:50:16 +02:00
warning ( " AttachModelEvent " , " Tag %s not found " , bone . c_str ( ) ) ;
2024-02-04 16:29:38 +01:00
obj - > NewAnim ( " idle " ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : RemoveAttachedModelEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-10-06 20:13:21 +02:00
str tag_name ;
int tag_num ;
int num ;
int i ;
Entity * ent ;
float fade_rate = 0 ;
Event * fade_event ;
str model_name ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tag_name = ev - > GetString ( 1 ) ;
tag_num = gi . Tag_NumForName ( edict - > tiki , tag_name ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
fade_rate = ev - > GetFloat ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
model_name = ev - > GetString ( 3 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( tag_num > = 0 ) {
num = numchildren ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; ( i < MAX_MODEL_CHILDREN ) & & num ; i + + ) {
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ( Entity * ) G_GetEntity ( children [ i ] ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ent - > edict - > s . tag_num = = tag_num ) {
if ( ! model_name . length ( ) | | model_name = = ent - > model ) {
if ( fade_rate ) {
fade_event = new Event ( EV_Fade ) ;
fade_event - > AddFloat ( fade_rate ) ;
fade_event - > AddFloat ( 0 ) ;
ent - > PostEvent ( fade_event , 0 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent - > PostEvent ( EV_Remove , fade_rate ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
num - - ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : AttachedModelAnimEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int tag_num ;
int num ;
int i ;
Entity * ent ;
str model_name ;
str anim_name ;
float crossblend_time ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tag_num = gi . Tag_NumForName ( edict - > tiki , ev - > GetString ( 1 ) . c_str ( ) ) ;
anim_name = ev - > GetString ( 2 ) ;
if ( ev - > NumArgs ( ) > = 3 ) {
crossblend_time = ev - > GetFloat ( 3 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > = 4 ) {
model_name = ev - > GetString ( 4 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( tag_num > = 0 ) {
num = numchildren ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// find the children that is glued to the specified tagnum
for ( i = 0 ; i < MAX_MODEL_CHILDREN & & num ; i + + ) {
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = G_GetEntity ( children [ i ] ) ;
if ( ent - > edict - > s . tag_num ! = tag_num ) {
// not matching the requested tag num
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( model_name . length ( ) & & str : : icmp ( model_name . c_str ( ) , ent - > model . c_str ( ) ) ) {
// different model
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
Event * newev = new Event ( EV_SetAnim ) ;
newev - > AddString ( anim_name ) ;
ent - > PostEvent ( newev , 0.f ) ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : DetachEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( edict - > s . parent = = ENTITYNUM_NONE ) {
return ;
}
detach ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : TakeDamageEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
takedamage = DAMAGE_YES ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : NoDamageEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
takedamage = DAMAGE_NO ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Gravity ( Event * ev )
2018-09-17 23:50:38 +02:00
{
2023-08-09 23:09:09 +02:00
gravity = ev - > GetFloat ( 1 ) ;
2018-09-17 23:50:38 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : UseBoundingBoxEvent ( Event * ev )
2018-09-17 23:50:38 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > r . svFlags | = SVF_USEBBOX ;
}
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : HurtEvent ( Event * ev )
{
Vector normal ;
float dmg ;
int means_of_death ;
Vector direction ;
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) < 1 ) {
dmg = 50 ;
} else {
dmg = ev - > GetFloat ( 1 ) ;
}
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
2023-08-15 01:27:35 +02:00
means_of_death = MOD_string_to_int ( ev - > GetString ( 2 ) ) ;
2023-08-09 23:09:09 +02:00
} else {
means_of_death = MOD_CRUSH ;
}
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
direction = ev - > GetVector ( 3 ) ;
direction . normalize ( ) ;
} else {
direction = vec_zero ;
}
2018-09-17 23:50:38 +02:00
2023-08-09 23:09:09 +02:00
normal = Vector ( orientation [ 0 ] ) ;
Damage ( world , world , dmg , centroid , direction , normal , dmg , 0 , means_of_death ) ;
2018-09-17 23:50:38 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : HealEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( IsDead ( ) ) {
ScriptError ( " cannot heal dead entities " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
health + = ev - > GetFloat ( 1 ) * max_health ;
if ( health > max_health ) {
health = max_health ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Censor ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Vector delta ;
float oldsize ;
float newsize ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
oldsize = size . length ( ) ;
setSolidType ( SOLID_NOT ) ;
setModel ( " censored.tik " ) ;
2023-09-27 23:21:34 +02:00
gi . TIKI_CalculateBounds ( edict - > tiki , 1 , mins , maxs ) ;
2023-08-09 23:09:09 +02:00
delta = maxs - mins ;
newsize = delta . length ( ) ;
edict - > s . scale = oldsize / newsize ;
mins * = edict - > s . scale ;
maxs * = edict - > s . scale ;
setSize ( mins , maxs ) ;
setOrigin ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : StationaryEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
setMoveType ( MOVETYPE_STATIONARY ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : TossEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
movetype = MOVETYPE_TOSS ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Explosion ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
str expmodel ;
str tag_name ;
//orientation_t orient;
Vector explosion_origin ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
expmodel = ev - > GetString ( 1 ) ;
explosion_origin = origin ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
tag_name = ev - > GetString ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//if ( GetRawTag( tag_name.c_str(), &orient, legs ) )
// VectorAdd( orient.origin, origin, explosion_origin );
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
GetTag ( tag_name . c_str ( ) , & explosion_origin ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ExplosionAttack ( explosion_origin , this , expmodel ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Shader ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-10-06 20:13:21 +02:00
str token ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( gi . modeltiki ( model ) ) {
gi . Printf ( " shader event being called on TIKI model \n " ) ;
}
//
// get sub shader command
//
token = ev - > GetString ( 1 ) ;
//
// WARNING: please change the Event decleration,
// to match this function, if flags are added or
// deleted the event must be updated.
//
if ( ! Q_stricmp ( token , " translation " ) ) {
float x , y ;
x = ev - > GetFloat ( 2 ) ;
y = ev - > GetFloat ( 3 ) ;
TRANSLATION_TO_PKT ( x , edict - > s . tag_num ) ;
TRANSLATION_TO_PKT ( y , edict - > s . skinNum ) ;
} else if ( ! Q_stricmp ( token , " offset " ) ) {
float x , y ;
x = ev - > GetFloat ( 2 ) ;
y = ev - > GetFloat ( 3 ) ;
OFFSET_TO_PKT ( x , edict - > s . tag_num ) ;
OFFSET_TO_PKT ( y , edict - > s . skinNum ) ;
} else if ( ! Q_stricmp ( token , " rotation " ) ) {
float rot ;
rot = ev - > GetFloat ( 2 ) ;
ROTATE_TO_PKT ( rot , edict - > s . tag_num ) ;
} else if ( ! Q_stricmp ( token , " wavebase " ) ) {
float base ;
base = ev - > GetFloat ( 2 ) ;
BASE_TO_PKT ( base , edict - > s . surfaces [ 0 ] ) ;
} else if ( ! Q_stricmp ( token , " waveamp " ) ) {
float amp ;
amp = ev - > GetFloat ( 2 ) ;
AMPLITUDE_TO_PKT ( amp , edict - > s . surfaces [ 1 ] ) ;
} else if ( ! Q_stricmp ( token , " wavephase " ) ) {
float phase ;
phase = ev - > GetFloat ( 2 ) ;
PHASE_TO_PKT ( phase , edict - > s . surfaces [ 2 ] ) ;
} else if ( ! Q_stricmp ( token , " wavefreq " ) ) {
float freq ;
freq = ev - > GetFloat ( 2 ) ;
FREQUENCY_TO_PKT ( freq , edict - > s . surfaces [ 3 ] ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DropToFloorEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
float range ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 0 ) {
range = ev - > GetFloat ( 1 ) ;
} else {
range = MAP_SIZE ;
}
if ( ! droptofloor ( range ) ) { }
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : isBoundTo ( Entity * master )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( ent = bindmaster ; ent ! = NULL ; ent = ent - > bindmaster ) {
if ( ent = = master ) {
return true ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
return false ;
2016-03-27 11:49:47 +02:00
}
2023-11-27 20:06:05 +01:00
void Entity : : bind ( Entity * master , qboolean use_my_angles )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
float mat [ 3 ] [ 3 ] ;
float local [ 3 ] [ 3 ] ;
Vector ang ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
assert ( master ) ;
if ( ! master ) {
warning ( " bind " , " Null master entity " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( master = = this ) {
warning ( " bind " , " Trying to bind to oneself. " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// unbind myself from my master
unbind ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
bindmaster = master ;
bind_use_my_angles = use_my_angles ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// We are now separated from our previous team and are either
// an individual, or have a team of our own. Now we can join
// the new bindmaster's team. Bindmaster must be set before
// joining the team, or we will be placed in the wrong position
// on the team.
joinTeam ( master ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// calculate local angles
TransposeMatrix ( bindmaster - > orientation , mat ) ;
R_ConcatRotations ( mat , orientation , local ) ;
MatrixToEulerAngles ( local , ang ) ;
setAngles ( ang ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
setLocalOrigin ( getParentVector ( localorigin - bindmaster - > origin ) ) ;
return ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : unbind ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * prev ;
Entity * next ;
Entity * last ;
Entity * ent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! bindmaster ) {
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
//bindmaster = NULL;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Check this GAMEFIX - should it be origin?
localorigin = Vector ( edict - > s . origin ) ;
localangles = Vector ( edict - > s . angles ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! teammaster ) {
bindmaster = NULL ;
//Teammaster already has been freed
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// We're still part of a team, so that means I have to extricate myself
// and any entities that are bound to me from the old team.
// Find the node previous to me in the team
prev = teammaster ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( ent = teammaster - > teamchain ; ent & & ( ent ! = this ) ; ent = ent - > teamchain ) {
prev = ent ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// If ent is not pointing to me, then something is very wrong.
assert ( ent ) ;
if ( ! ent ) {
gi . Printf ( " unbind " , " corrupt team chain \n " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Find the last node in my team that is bound to me.
// Also find the first node not bound to me, if one exists.
last = this ;
for ( next = teamchain ; next ! = NULL ; next = next - > teamchain ) {
if ( ! next - > isBoundTo ( this ) ) {
break ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Tell them I'm now the teammaster
next - > teammaster = this ;
last = next ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// disconnect the last member of our team from the old team
last - > teamchain = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// connect up the previous member of the old team to the node that
// follow the last node bound to me (if one exists).
if ( teammaster ! = this ) {
prev - > teamchain = next ;
if ( ! next & & ( teammaster = = prev ) ) {
prev - > teammaster = NULL ;
}
} else if ( next ) {
// If we were the teammaster, then the nodes that were not bound to me are now
// a disconnected chain. Make them into their own team.
for ( ent = next ; ent - > teamchain ! = NULL ; ent = ent - > teamchain ) {
ent - > teammaster = next ;
}
next - > teammaster = next ;
next - > flags & = ~ FL_TEAMSLAVE ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// If we don't have anyone on our team, then clear the team variables.
if ( teamchain ) {
// make myself my own team
teammaster = this ;
} else {
// no longer a team
teammaster = NULL ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
flags & = ~ FL_TEAMSLAVE ;
bindmaster = NULL ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventUnglue ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
unglue ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : GlueEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent ;
qboolean glueAngles ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
glueAngles = ev - > GetInteger ( 2 ) ;
} else {
glueAngles = qtrue ;
}
ent = ev - > GetEntity ( 1 ) ;
if ( ent ) {
glue ( ent , glueAngles , qfalse ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DuckableGlueEvent ( Event * ev )
{
Entity * ent ;
qboolean glueAngles ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
glueAngles = ev - > GetInteger ( 2 ) ;
} else {
glueAngles = qtrue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ev - > GetEntity ( 1 ) ;
if ( ent ) {
glue ( ent , glueAngles , qtrue ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : MakeClayPidgeon ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > r . contents = CONTENTS_CLAYPIDGEON ;
setSolidType ( SOLID_BBOX ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventUnbind ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
unbind ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : BindEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent ;
ent = ev - > GetEntity ( 1 ) ;
if ( ent ) {
2023-11-27 20:06:05 +01:00
bind ( ent , false ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
Vector Entity : : getParentVector ( Vector vec )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Vector pos ;
if ( ! bindmaster ) {
return vec ;
}
pos [ 0 ] = vec * bindmaster - > orientation [ 0 ] ;
pos [ 1 ] = vec * bindmaster - > orientation [ 1 ] ;
pos [ 2 ] = vec * bindmaster - > orientation [ 2 ] ;
return pos ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
//
// Team methods
//
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : joinTeam ( Entity * teammember )
{
Entity * ent ;
Entity * master ;
Entity * prev ;
Entity * next ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( teammaster & & ( teammaster ! = this ) ) {
quitTeam ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
assert ( teammember ) ;
if ( ! teammember ) {
warning ( " joinTeam " , " Null entity " ) ;
return ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
master = teammember - > teammaster ;
if ( ! master ) {
master = teammember ;
teammember - > teammaster = teammember ;
teammember - > teamchain = this ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// make anyone who's bound to me part of the new team
for ( ent = teamchain ; ent ! = NULL ; ent = ent - > teamchain ) {
ent - > teammaster = master ;
}
} else {
// skip past the chain members bound to the entity we're teaming up with
prev = teammember ;
next = teammember - > teamchain ;
if ( bindmaster ) {
// if we have a bindmaster, joing after any entities bound to the entity
// we're joining
while ( next & & ( ( Entity * ) next ) - > isBoundTo ( teammember ) ) {
prev = next ;
next = next - > teamchain ;
}
} else {
// if we're not bound to someone, then put us at the end of the team
while ( next ) {
prev = next ;
next = next - > teamchain ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// make anyone who's bound to me part of the new team and
// also find the last member of my team
for ( ent = this ; ent - > teamchain ! = NULL ; ent = ent - > teamchain ) {
ent - > teamchain - > teammaster = master ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
prev - > teamchain = this ;
ent - > teamchain = next ;
}
teammaster = master ;
flags | = FL_TEAMSLAVE ;
}
void Entity : : quitTeam ( void )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent ;
if ( ! teammaster ) {
return ;
}
if ( teammaster = = this ) {
if ( ! teamchain - > teamchain ) {
teamchain - > teammaster = NULL ;
} else {
// make next teammate the teammaster
for ( ent = teamchain ; ent ; ent = ent - > teamchain ) {
ent - > teammaster = teamchain ;
}
}
teamchain - > flags & = ~ FL_TEAMSLAVE ;
} else {
assert ( flags & FL_TEAMSLAVE ) ;
assert ( teammaster - > teamchain ) ;
ent = teammaster ;
while ( ent - > teamchain ! = this ) {
// this should never happen
assert ( ent - > teamchain ) ;
ent = ent - > teamchain ;
}
ent - > teamchain = teamchain ;
if ( ! teammaster - > teamchain ) {
teammaster - > teammaster = NULL ;
}
}
teammaster = NULL ;
teamchain = NULL ;
flags & = ~ FL_TEAMSLAVE ;
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventQuitTeam ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
quitTeam ( ) ;
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : JoinTeam ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ev - > GetEntity ( 1 ) ;
if ( ent ) {
joinTeam ( ent ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : AddToSoundManager ( Event * ev )
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
{
SoundMan . AddEntity ( this ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
inline qboolean Entity : : HitSky ( trace_t * trace )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
assert ( trace ) ;
if ( trace - > surfaceFlags & SURF_SKY ) {
return true ;
}
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
qboolean Entity : : HitSky ( void )
{
return HitSky ( & level . impact_trace ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : NoLerpThisFrame ( void )
{
edict - > s . eFlags ^ = EF_TELEPORT_BIT ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Postthink ( void ) { }
void Entity : : TouchTriggersEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
flags | = FL_TOUCH_TRIGGERS ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : DeathSinkStart ( Event * ev )
{
if ( g_gametype - > integer ) {
PostEvent ( EV_Remove , 5.0f ) ;
} else {
// Start the sinking
ProcessEvent ( EV_DeathSink ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DeathSink ( Event * ev )
{
// Sink just a little
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( g_gametype - > integer ) {
origin [ 2 ] - = 0.2f ;
setOrigin ( origin ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Make sure the sink happens again next frame
PostEvent ( EV_DeathSink , FRAMETIME ) ;
} else {
Entity * player = G_GetEntity ( 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Remove the entity when the player isn't supposed to see it
if ( player & & gi . AreasConnected ( this - > edict - > r . areanum , player - > edict - > r . areanum ) ) {
PostEvent ( EV_DeathSink , 1.0f ) ;
} else {
PostEvent ( EV_Remove , 0 ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : VelocityModified ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DetachAllChildren ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < MAX_MODEL_CHILDREN ; i + + ) {
Entity * ent ;
if ( children [ i ] = = ENTITYNUM_NONE ) {
continue ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ( Entity * ) G_GetEntity ( children [ i ] ) ;
if ( ent ) {
ent - > PostEvent ( EV_Remove , 0 ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
bool monkeycheck = false ;
cvar_t * thereisnomonkey ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
qboolean Entity : : CheckEventFlags ( Event * event )
{
int flags = GetFlags ( event ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// Special handling of console events
if ( ! ( flags & ( EV_CONSOLE | EV_CHEAT ) ) ) {
if ( isSubclassOf ( Entity ) ) {
Entity * ent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ( Entity * ) this ;
gi . SendServerCommand (
2023-09-07 18:05:49 +02:00
ent - > edict - g_entities , " print \" Command '%s' not available from console \n \" " , event - > getName ( )
2023-08-09 23:09:09 +02:00
) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// don't process
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// don't allow console cheats unless the server says it's ok.
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ( flags & EV_CHEAT ) ) {
if ( ! monkeycheck ) {
thereisnomonkey = gi . Cvar_Get ( " thereisnomonkey " , " 0 " , CVAR_TEMP ) ;
monkeycheck = true ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! thereisnomonkey - > integer ) {
2023-08-15 01:27:35 +02:00
gi . cvar_set ( " cheats " , " 0 " ) ;
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! sv_cheats - > integer ) {
if ( isSubclassOf ( Entity ) ) {
Entity * ent ;
const char * szConv =
gi . LV_ConvertString ( " You must run the server with '+set cheats 1' to enable this command. " ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ent = ( Entity * ) this ;
gi . SendServerCommand ( ent - > edict - g_entities , " print \" %s \n \" " , szConv ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// don't process
return false ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// ok to process
return true ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetMovementStealth ( float fStealthScale )
{
if ( fStealthScale < 0.0f ) {
stealthMovementScale = 0.0f ;
} else {
stealthMovementScale = fStealthScale ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventMovementStealth ( Event * ev )
{
SetMovementStealth ( ev - > GetFloat ( 1 ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : PusherEvent ( Event * ev )
{
Entity * inflictor ;
Entity * attacker ;
Vector dir ;
Vector momentum ;
float m ;
float force ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( movetype < = MOVETYPE_NOCLIP | | movetype = = MOVETYPE_FLYMISSILE | | movetype = = MOVETYPE_STOP
| | movetype = = MOVETYPE_PUSH ) {
return ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
inflictor = ev - > GetEntity ( 1 ) ;
attacker = ev - > GetEntity ( 2 ) ;
dir = ev - > GetVector ( 3 ) ;
force = ev - > GetFloat ( 4 ) ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
m = mass ;
if ( m < 20 ) {
m = 20.0f ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
m = 1000.0f / m ;
momentum = dir * force * m ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
velocity + = momentum ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : AlwaysDraw ( Event * ev )
{
edict - > s . renderfx | = RF_ALWAYSDRAW ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : NormalDraw ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > s . renderfx & = RF_DONTDRAW | RF_ALWAYSDRAW ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : NeverDraw ( Event * ev )
{
edict - > s . renderfx | = RF_DONTDRAW ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
//*************************************************************************
//
// BIND code
//
//*************************************************************************
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : glue ( Entity * master , qboolean use_my_angles , qboolean can_duck )
{
int iNumGlues ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( m_pGlueMaster ) {
unglue ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! master ) {
warning ( " glue " , " Cannot glue to master because of: Master is NULL \n " ) ;
return ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( master = = this ) {
warning ( " glue " , " Cannot glue to master because of: Binding an entity to itself \n " ) ;
return ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
iNumGlues = master - > m_iNumGlues ;
if ( iNumGlues + 1 > MAX_GLUE_CHILDREN ) {
warning ( " glue " , " Cannot glue to master because of: MAX_GLUE_CHILDREN reached \n " ) ;
return ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
for ( int i = 0 ; i < iNumGlues ; i + + ) {
if ( master - > m_pGlues [ i ] = = this ) {
warning ( " glue " , " Cannot glue to master because of: entity is already glued \n " ) ;
return ;
}
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
master - > m_pGlues [ iNumGlues ] = this ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( use_my_angles ) {
m_bGlueAngles = true ;
master - > m_pGluesFlags [ iNumGlues ] = GL_USEANGLES ;
} else {
m_bGlueAngles = false ;
master - > m_pGluesFlags [ iNumGlues ] = 0 ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
m_pGlueMaster = master ;
m_bGlueDuckable = can_duck = = qtrue ;
master - > m_iNumGlues + + ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
setAngles ( master - > angles ) ;
setOrigin ( master - > origin ) ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : unglue ( void )
{
int iNumGlues ;
int i ;
Entity * master = m_pGlueMaster ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( ! master ) {
return ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
iNumGlues = master - > m_iNumGlues ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < iNumGlues ; i + + ) {
if ( master - > m_pGlues [ i ] = = this ) {
break ;
}
}
if ( i ! = iNumGlues ) {
for ( ; i < iNumGlues - 1 ; i + + ) {
master - > m_pGlues [ i ] = master - > m_pGlues [ i + 1 ] ;
master - > m_pGluesFlags [ i ] = master - > m_pGluesFlags [ i + 1 ] ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
master - > m_iNumGlues - - ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
m_pGlueMaster = NULL ;
m_bGlueAngles = false ;
}
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetTagPositionAndOrientation ( int tagnum , orientation_t * new_or )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
orientation_t tag_or ;
float axis [ 3 ] [ 3 ] ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
GetRawTag ( tagnum , & tag_or ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
AnglesToAxis ( angles , axis ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
VectorCopy ( origin , new_or - > origin ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 0 ; i < 3 ; i + + ) {
2024-09-02 19:03:15 +02:00
VectorMA ( new_or - > origin , tag_or . origin [ i ] , axis [ i ] , new_or - > origin ) ;
2023-08-09 23:09:09 +02:00
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
MatrixMultiply ( tag_or . axis , axis , new_or - > axis ) ;
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetTagPosition ( Event * ev )
{
Vector pos ;
str tagname ;
int tagnum ;
int i ;
orientation_t tag_or ;
float axis [ 3 ] [ 3 ] ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! edict - > tiki ) {
ScriptError ( " Entity '%s' at %.2f %.2f %.2f has no model. " , targetname . c_str ( ) , origin [ 0 ] , origin [ 1 ] , origin [ 2 ] ) ;
}
tagname = ev - > GetString ( 1 ) ;
tagnum = gi . Tag_NumForName ( edict - > tiki , tagname ) ;
if ( tagnum < 0 ) {
ScriptError ( " Could not find tag '%s' in '%s' " , tagname . c_str ( ) , edict - > tiki - > name ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tag_or = G_TIKI_Orientation ( edict , tagnum & TAG_MASK ) ;
AnglesToAxis ( angles , axis ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
pos = origin ;
for ( i = 0 ; i < 3 ; i + + ) {
VectorMA ( pos , tag_or . origin [ i ] , axis [ i ] , pos ) ;
}
ev - > AddVector ( pos ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetTagAngles ( Event * ev )
{
orientation_t orient ;
Vector ang ;
str tagname ;
int tagnum ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! edict - > tiki ) {
ScriptError ( " Entity '%s' at %.2f %.2f %.2f has no model. " , targetname . c_str ( ) , origin [ 0 ] , origin [ 1 ] , origin [ 2 ] ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tagname = ev - > GetString ( 1 ) ;
tagnum = gi . Tag_NumForName ( edict - > tiki , tagname ) ;
if ( tagnum < 0 ) {
ScriptError ( " Could not find tag '%s' in '%s' " , tagname . c_str ( ) , edict - > tiki - > name ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
GetTagPositionAndOrientation ( tagnum , & orient ) ;
MatrixToEulerAngles ( orient . axis , ang ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddVector ( ang ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : IsTouching ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Entity * ent = ev - > GetEntity ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ent ) {
ScriptError ( " IsTouching used with a NULL entity. " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( IsTouching ( ent ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : IsInside ( Event * ev )
{
Entity * ent = ev - > GetEntity ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ent ) {
ScriptError ( " IsInside used with a NULL entity. " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( IsInside ( ent ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : CanSeeInternal ( Event * ev , bool bNoEnts )
{
float fov = 0.0f ;
float distance = 0.0f ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) < = 0 | | ev - > NumArgs ( ) > 3 ) {
ScriptError ( " cansee should have 1, 2 or 3 arguments " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
distance = ev - > GetFloat ( 3 ) ;
if ( distance < 0 ) {
ScriptError ( " distance must be >= 0 " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
fov = ev - > GetFloat ( 2 ) ;
if ( fov < 0.0f | | fov > 360.0f ) {
ScriptError ( " fov must be in range 0 <= fov <= 360 " ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > IsVectorAt ( 1 ) ) {
Vector org = ev - > GetVector ( 1 ) ;
ev - > AddInteger ( CanSee ( org , fov , distance , bNoEnts ) ) ;
} else {
Entity * ent = ev - > GetEntity ( 1 ) ;
if ( ! ent ) {
ScriptError ( " NULL entity in parameter 1 " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( CanSee ( ent , fov , distance , bNoEnts ) ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : CanSee ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
CanSeeInternal ( ev , false ) ;
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : CanSeeNoEnts ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
CanSeeInternal ( ev , true ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventInPVS ( Event * ev )
{
ev - > AddInteger ( gi . AreasConnected ( edict - > r . areanum , ev - > GetEntity ( 1 ) - > edict - > r . areanum ) ! = 0 ) ;
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetShaderData ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > s . shader_data [ 0 ] = ev - > GetFloat ( 1 ) ;
edict - > s . shader_data [ 1 ] = ev - > GetFloat ( 2 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : MPrintf ( const char * fmt , . . . )
{
va_list argptr ;
char msg [ MAXPRINTMSG ] ;
2016-03-27 11:49:47 +02:00
2024-02-14 20:58:08 +01:00
if ( g_monitorNum - > integer = = entnum | | g_monitor - > string [ 0 ] & & g_monitor - > string = = targetname ) {
2023-08-09 23:09:09 +02:00
va_start ( argptr , fmt ) ;
Q_vsnprintf ( msg , sizeof ( msg ) , fmt , argptr ) ;
va_end ( argptr ) ;
Com_Printf ( " %s " , msg ) ;
}
2023-07-30 21:21:00 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetVelocity ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
ev - > AddVector ( velocity ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetVelocity ( Event * ev )
{
velocity = ev - > GetVector ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : GetAVelocity ( Event * ev )
{
ev - > AddVector ( avelocity ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : DoForceActivate ( void )
{
edict - > r . lastNetTime = level . inttime ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : ForceActivate ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
DoForceActivate ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventTrace ( Event * ev )
{
Vector start , end , mins , maxs ;
2023-08-19 00:58:06 +02:00
int mask = MASK_SOLID ;
2023-08-09 23:09:09 +02:00
Entity * ent ;
trace_t trace ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
mins = vec_zero ;
maxs = vec_zero ;
ent = NULL ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
start = ev - > GetVector ( 1 ) ;
end = ev - > GetVector ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
if ( ev - > GetInteger ( 3 ) ) {
mask = 1 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 3 ) {
mins = ev - > GetVector ( 4 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 4 ) {
maxs = ev - > GetVector ( 5 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 5 ) {
ent = G_GetEntity ( ev - > GetInteger ( 6 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// call trace
2023-08-19 00:58:06 +02:00
trace = G_Trace ( start , mins , maxs , end , ent , mask , qfalse , " Entity::EventTrace " ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddVector ( trace . endpos ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventSightTrace ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Vector start , end , mins , maxs ;
2023-08-19 00:58:06 +02:00
int mask = MASK_SOLID ;
2023-08-09 23:09:09 +02:00
Entity * ent = nullptr ;
qboolean hit = qfalse ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
mins = vec_zero ;
maxs = vec_zero ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
start = ev - > GetVector ( 1 ) ;
end = ev - > GetVector ( 2 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 2 ) {
if ( ev - > GetInteger ( 3 ) ) {
mask = 1 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 3 ) {
mins = ev - > GetVector ( 4 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 4 ) {
maxs = ev - > GetVector ( 5 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 5 ) {
ent = G_GetEntity ( ev - > GetInteger ( 6 ) ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
hit = G_SightTrace ( start , mins , maxs , end , ent , NULL , mask , qfalse , " Entity::EventSightTrace " ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( hit ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : ClientThink ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EndFrame ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : CalcBlend ( void ) { }
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : ShowInfo ( float fDot , float fDist )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
char szText [ 512 ] ;
if ( fDot > 0.94999999 & & fDist < 1024.0 & & fDist > 64.0 ) {
i = sprintf ( szText , " %i:%i " , entnum , radnum ) ;
if ( targetname . length ( ) ) {
i = sprintf ( & szText [ i ] , " :%s " , targetname . c_str ( ) ) ;
}
if ( health ! = 0 ) {
sprintf ( & szText [ i ] , " :%.1f " , health ) ;
}
G_DebugString ( Vector ( origin . x + 0 , origin . y + 0 , origin . z + maxs . z + 65 ) , 1.0 , 1.0 , 1.0 , 1.0 , szText ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
bool Entity : : AutoArchiveModel ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : ConnectPaths ( void )
{
PathNode * node ;
int to ;
int j ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( int i = 0 ; i < m_iNumBlockedPaths ; i + + ) {
to = m_BlockedPaths [ i ] . to ;
node = PathManager . pathnodes [ m_BlockedPaths [ i ] . from ] ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
j = node - > virtualNumChildren ;
pathway_t * pathway = & node - > Child [ j ] ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
do {
j - - ;
pathway - - ;
} while ( pathway - > node ! = to ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
pathway - > numBlockers - - ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! pathway - > numBlockers ) {
node - > ConnectChild ( j ) ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
m_iNumBlockedPaths = 0 ;
if ( m_BlockedPaths ) {
2024-06-23 00:24:20 +02:00
delete [ ] m_BlockedPaths ;
2023-08-09 23:09:09 +02:00
m_BlockedPaths = NULL ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : DisconnectPaths ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
int j ;
PathNode * node ;
pathway_t * pathway ;
pathway_ref paths [ 1024 ] ;
vec3_t mins ;
vec3_t maxs ;
gentity_t * collision_ent ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( m_BlockedPaths ) {
ConnectPaths ( ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( IsSubclassOfVehicle ( ) ) {
VehicleCollisionEntity * ent = ( ( Vehicle * ) this ) - > GetCollisionEntity ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! ent ) {
return ;
}
collision_ent = ent - > edict ;
} else {
collision_ent = edict ;
}
VectorSet ( mins , - 15.0f , - 15.0f , 0 ) ;
VectorSet ( maxs , 15.0f , 15.0f , 94.0f ) ;
for ( i = 0 ; i < PathManager . nodecount ; i + + ) {
node = PathManager . pathnodes [ i ] ;
for ( j = node - > virtualNumChildren - 1 ; j > = 0 ; j - - ) {
pathway = & node - > Child [ j ] ;
if ( ! gi . SightTraceEntity ( collision_ent , pathway - > pos1 , mins , maxs , pathway - > pos2 , MASK_PATHSOLID , qtrue ) ) {
paths [ m_iNumBlockedPaths ] . from = node - > nodenum ;
paths [ m_iNumBlockedPaths ] . to = pathway - > node ;
m_iNumBlockedPaths + + ;
pathway - > numBlockers + + ;
if ( pathway - > numBlockers = = 1 ) {
node - > DisconnectChild ( j ) ;
}
}
}
}
if ( m_iNumBlockedPaths ) {
m_BlockedPaths = new pathway_ref [ m_iNumBlockedPaths ] ;
for ( i = 0 ; i < m_iNumBlockedPaths ; i + + ) {
m_BlockedPaths [ i ] = paths [ i ] ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventConnectPaths ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
ConnectPaths ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventDisconnectPaths ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
DisconnectPaths ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Delete ( void )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
// Delete the entity the next frame
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( g_iInThinks ) {
PostEvent ( EV_Remove , 0 ) ;
} else {
delete this ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Remove ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) ) {
ScriptError ( " Arguments not allowed. " ) ;
}
Delete ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventSoundDone ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int channelNum = ev - > GetInteger ( 1 ) ;
str sfxName = ev - > GetString ( 2 ) ;
if ( gi . S_IsSoundPlaying ( channelNum , sfxName ) ) {
// Repost the event
Event * event = new Event ( EV_SoundDone ) ;
event - > AddInteger ( channelNum ) ;
event - > AddString ( sfxName ) ;
PostEvent ( event , level . frametime ) ;
} else {
Unregister ( STRING_SOUNDDONE ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : VolumeDamage ( float damage )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int i ;
int numtouch ;
Entity * ent ;
int touch [ MAX_GENTITIES ] ;
numtouch = gi . AreaEntities ( absmin , absmax , touch , MAX_GENTITIES ) ;
for ( i = 0 ; i < numtouch ; i + + ) {
ent = G_GetEntity ( touch [ i ] ) ;
ent - > Damage ( world , world , damage , origin , vec_zero , vec_zero , 0 , DAMAGE_RADIUS , MOD_EXPLOSION ) ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventVolumeDamage ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
VolumeDamage ( ev - > GetFloat ( 1 ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : Archive ( Archiver & arc )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int tempInt ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
SimpleEntity : : Archive ( arc ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
G_ArchiveEdict ( arc , edict ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveInteger ( & entnum ) ;
arc . ArchiveInteger ( & radnum ) ;
arc . ArchiveInteger ( & spawnflags ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveString ( & model ) ;
2023-11-26 19:49:51 +01:00
if ( arc . Loading ( ) & & AutoArchiveModel ( ) ) {
if ( model . length ( ) & & model [ 0 ] = = ' * ' ) {
// set the brush model
edict - > s . modelindex = atoi ( model . c_str ( ) + 1 ) ;
} else {
setModel ( model ) ;
}
2023-08-09 23:09:09 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveVector ( & mins ) ;
arc . ArchiveVector ( & maxs ) ;
arc . ArchiveVector ( & absmin ) ;
arc . ArchiveVector ( & absmax ) ;
arc . ArchiveVector ( & velocity ) ;
arc . ArchiveVector ( & accel ) ;
arc . ArchiveVector ( & avelocity ) ;
arc . ArchiveVector ( & aaccel ) ;
arc . ArchiveVector ( & size ) ;
arc . ArchiveInteger ( & movetype ) ;
arc . ArchiveInteger ( & mass ) ;
arc . ArchiveFloat ( & gravity ) ;
arc . ArchiveRaw ( orientation , sizeof ( orientation ) ) ;
if ( arc . Saving ( ) ) {
if ( groundentity ) {
tempInt = groundentity - g_entities ;
} else {
tempInt = - 1 ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveInteger ( & tempInt ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( arc . Loading ( ) ) {
if ( tempInt = = - 1 ) {
groundentity = NULL ;
} else {
groundentity = & g_entities [ tempInt ] ;
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveRaw ( & groundplane , sizeof ( groundplane ) ) ;
arc . ArchiveInteger ( & groundcontents ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveInteger ( & numchildren ) ;
arc . ArchiveRaw ( children , sizeof ( children ) ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveFloat ( & lightRadius ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveString ( & moveteam ) ;
arc . ArchiveObjectPointer ( ( Class * * ) & teamchain ) ;
arc . ArchiveObjectPointer ( ( Class * * ) & teammaster ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveObjectPointer ( ( Class * * ) & bindmaster ) ;
arc . ArchiveBoolean ( & bind_use_my_angles ) ;
arc . ArchiveVector ( & localorigin ) ;
arc . ArchiveVector ( & localangles ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
// add to target list to rebuild targetlists
arc . ArchiveString ( & killtarget ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveFloat ( & health ) ;
arc . ArchiveFloat ( & max_health ) ;
arc . ArchiveInteger ( & deadflag ) ;
arc . ArchiveInteger ( & flags ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
arc . ArchiveInteger ( & watertype ) ;
arc . ArchiveInteger ( & waterlevel ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ArchiveEnum ( takedamage , damage_t ) ;
2016-03-27 11:49:47 +02:00
2023-11-27 20:06:05 +01:00
arc . ArchiveSafePointer ( & enemy ) ;
arc . ArchiveFloat ( & pain_finished ) ;
arc . ArchiveFloat ( & damage_debounce_time ) ;
arc . ArchiveInteger ( & damage_type ) ;
2023-08-09 23:09:09 +02:00
arc . ArchiveInteger ( & m_iNumGlues ) ;
2016-03-27 11:49:47 +02:00
2023-08-13 20:19:51 +02:00
for ( i = 0 ; i < MAX_GLUE_CHILDREN ; i + + ) {
2023-08-09 23:09:09 +02:00
arc . ArchiveSafePointer ( & m_pGlues [ i ] ) ;
arc . ArchiveInteger ( & m_pGluesFlags [ i ] ) ;
}
arc . ArchiveObjectPointer ( ( Class * * ) & m_pGlueMaster ) ;
arc . ArchiveBool ( & m_bGlueAngles ) ;
2023-11-27 20:06:05 +01:00
arc . ArchiveBool ( & m_bGlueDuckable ) ;
2023-08-09 23:09:09 +02:00
arc . ArchiveBoolean ( & detach_at_death ) ;
arc . ArchiveFloat ( & stealthMovementScale ) ;
arc . ArchiveInteger ( & m_iNumBlockedPaths ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( arc . Loading ( ) ) {
m_BlockedPaths = new pathway_ref [ m_iNumBlockedPaths ] ;
}
for ( i = 0 ; i < m_iNumBlockedPaths ; i + + ) {
arc . ArchiveShort ( & m_BlockedPaths [ i ] . from ) ;
arc . ArchiveShort ( & m_BlockedPaths [ i ] . to ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
immunities . Archive ( arc ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventGetNormalHealth ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
ev - > AddFloat ( health / max_health * 100 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventNormalDamage ( Event * ev )
{
Vector position = vec_zero , direction , normal ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
Entity * attacker = world ;
float damage ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
normal = direction = Vector ( 0 , 1 , 0 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
int numArgs = ev - > NumArgs ( ) ;
if ( numArgs = = 1 ) {
damage = ev - > GetFloat ( 1 ) / 100 * max_health ;
} else if ( numArgs = = 2 ) {
damage = ev - > GetFloat ( 1 ) / 100 * max_health ;
direction = ev - > GetVector ( 2 ) ;
} else {
ScriptError ( " Wrong number of arguments for normal_damage. \n " ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
Event e1 ( EV_Damage ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
e1 . AddEntity ( attacker ) ; //attacker
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
e1 . AddFloat ( damage ) ; //damage
e1 . AddEntity ( attacker ) ; //inflictor
e1 . AddVector ( position ) ; //position
e1 . AddVector ( direction ) ; //direction
e1 . AddVector ( normal ) ; //normal
e1 . AddInteger ( 0 ) ; //knockback
e1 . AddInteger ( DAMAGE_NONE ) ; //damageflags
e1 . AddInteger ( MOD_NONE ) ; //meansofdeath
2023-08-11 01:33:49 +02:00
e1 . AddInteger ( HITLOC_GENERAL ) ; //location
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
ProcessEvent ( e1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : DrawBoundingBox ( int showbboxes )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( showbboxes > = 100 ) {
if ( g_monitorNum - > integer ! = entnum ) {
if ( ! * g_monitor - > string | | g_monitor - > string ! = targetname ) {
return ;
}
}
showbboxes - = 100 ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
switch ( showbboxes ) {
case 1 :
if ( edict - > s . solid ) {
2024-02-26 19:56:35 +01:00
G_DebugRotatedBBox ( origin , angles , mins , maxs , 1 , 1 , 0 , 1 ) ;
2023-08-09 23:09:09 +02:00
}
break ;
case 2 :
if ( edict - > s . solid ) {
G_DebugBBox ( vec_zero , edict - > r . absmin , edict - > r . absmax , 1 , 0 , 1 , 1 ) ;
}
break ;
case 3 :
if ( edict - > tiki & & ! ( edict - > s . renderfx & RF_DONTDRAW ) ) {
2024-02-26 19:56:35 +01:00
G_DebugRotatedBBox ( origin , angles , mins , maxs , 1 , 1 , 0 , 1 ) ;
2023-08-09 23:09:09 +02:00
}
break ;
case 4 :
2024-02-26 19:56:35 +01:00
G_DebugRotatedBBox ( origin , angles , mins , maxs , 1 , 1 , 0 , 1 ) ;
break ;
case 7 :
if ( edict - > tiki & & ! ( edict - > s . renderfx & RF_DONTDRAW ) ) {
Vector vMins , vMaxs ;
gi . TIKI_CalculateBounds ( edict - > tiki , edict - > s . scale , vMins , vMaxs ) ;
if ( ! VectorCompare ( vMins , vec_zero ) | | ! VectorCompare ( vMaxs , vec_zero ) ) {
if ( edict - > s . parent ! = ENTITYNUM_NONE & & edict - > s . tag_num > = 0 ) {
int i ;
Vector vAng ;
orientation_t oTag , oBox ;
Entity * pParent ;
pParent = G_GetEntity ( edict - > s . parent ) ;
AnglesToAxis ( pParent - > angles , pParent - > orientation ) ;
oTag = G_TIKI_Orientation ( pParent - > edict , edict - > s . tag_num & TAG_MASK ) ;
VectorCopy ( pParent - > origin , oBox . origin ) ;
for ( i = 0 ; i < 3 ; i + + ) {
VectorMA ( oBox . origin , oTag . origin [ i ] , pParent - > orientation [ i ] , oBox . origin ) ;
}
MatrixMultiply ( oTag . axis , pParent - > orientation , oBox . axis ) ;
MatrixToEulerAngles ( oBox . axis , vAng ) ;
G_DebugRotatedBBox ( oBox . origin , vAng , vMins , vMaxs , 0 , 1 , 1 , 1 ) ;
} else {
G_DebugRotatedBBox ( origin , angles , vMins , vMaxs , 0 , 1 , 1 , 1 ) ;
}
}
}
break ;
case 8 :
if ( edict - > tiki & & ! ( edict - > s . renderfx & RF_DONTDRAW ) ) {
G_DebugRotatedBBox ( origin , angles , mins , maxs , 1 , 1 , 0 , 1 ) ;
G_DebugBBox ( origin , Vector ( - 4 , - 4 , - 4 ) , Vector ( 4 , 4 , 4 ) , 0 , 1 , 1 , 1 ) ;
}
2023-08-09 23:09:09 +02:00
break ;
default :
if ( IsSubclassOfAnimate ( ) & & edict - > tiki ) {
Animate * anim ;
vec3_t mins , maxs ;
anim = ( Animate * ) this ;
// FIXME
G_DebugBBox ( origin , mins , maxs , 0 , 1 , 0 , 1 ) ;
} else {
G_DebugBBox ( origin , mins , maxs , 1 , 1 , 0 , 1 ) ;
}
break ;
}
2024-02-26 19:56:35 +01:00
// FIXME: not implemented (implement the rest...)
2023-08-09 23:09:09 +02:00
}
2023-09-23 19:38:04 +02:00
qboolean Entity : : IsDead ( void ) const
2023-08-09 23:09:09 +02:00
{
return deadflag ! = DEAD_NO ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : AddImmunity ( Event * ev )
{
str immune_string ;
int new_immunity ;
int number_of_immunities ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
number_of_immunities = ev - > NumArgs ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = number_of_immunities ; i + + ) {
immune_string = ev - > GetString ( i ) ;
2016-03-27 11:49:47 +02:00
2023-08-15 01:27:35 +02:00
new_immunity = MOD_string_to_int ( immune_string ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( new_immunity ! = - 1 ) {
immunities . AddUniqueObject ( new_immunity ) ;
}
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : RemoveImmunity ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
str immune_string ;
int old_immunity ;
int number_of_immunities ;
int i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
number_of_immunities = ev - > NumArgs ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = number_of_immunities ; i + + ) {
immune_string = ev - > GetString ( i ) ;
2016-03-27 11:49:47 +02:00
2023-08-15 01:27:35 +02:00
old_immunity = MOD_string_to_int ( immune_string ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( old_immunity ! = - 1 & & immunities . ObjectInList ( old_immunity ) ) {
immunities . RemoveObject ( old_immunity ) ;
}
}
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
qboolean Entity : : Immune ( int meansofdeath )
{
int number_of_immunities , i ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
number_of_immunities = immunities . NumObjects ( ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
for ( i = 1 ; i < = number_of_immunities ; i + + ) {
if ( meansofdeath = = immunities . ObjectAt ( i ) ) {
return true ;
}
}
return false ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : PathnodeClaimRevoked ( PathNode * node )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
return node - > Relinquish ( ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : BlocksAIMovement ( ) const
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : AIDontFace ( void ) const
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
return true ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventGetEntnum ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( entnum ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventGetClassname ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
ev - > AddString ( getClassname ( ) ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetModelEvent ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
setModel ( ev - > GetString ( 1 ) ) ;
}
void Entity : : EventSetRadnum ( Event * ev )
{
radnum = ev - > GetInteger ( 1 ) ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : EventGetRadnum ( Event * ev )
{
ev - > AddInteger ( radnum ) ;
}
void Entity : : EventSetRotatedBbox ( Event * ev )
{
if ( ev - > GetInteger ( 1 ) ) {
edict - > s . eFlags | = EF_LINKANGLES ;
} else {
edict - > s . eFlags & = ~ EF_LINKANGLES ;
}
setAngles ( angles ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventGetRotatedBbox ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
ev - > AddInteger ( ( edict - > s . eFlags & EF_LINKANGLES ) ? 1 : 0 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventSinglePlayerCommand ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER & & ! g_realismmode - > integer ) {
2024-02-23 23:19:59 +01:00
Event * newev = new Event ( ev - > GetToken ( 1 ) , ev - > NumArgs ( ) - 1 ) ;
2023-07-30 21:21:00 +02:00
for ( int i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
newev - > AddToken ( ev - > GetToken ( i ) ) ;
}
ProcessEvent ( newev ) ;
2023-08-09 23:09:09 +02:00
}
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventMultiPlayerCommand ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & ! g_realismmode - > integer ) {
2024-02-23 23:19:59 +01:00
Event * newev = new Event ( ev - > GetToken ( 1 ) , ev - > NumArgs ( ) - 1 ) ;
2023-07-30 21:21:00 +02:00
for ( int i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
newev - > AddToken ( ev - > GetToken ( i ) ) ;
}
ProcessEvent ( newev ) ;
2023-08-09 23:09:09 +02:00
}
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventRealismModeCommand ( Event * ev )
2023-07-30 21:21:00 +02:00
{
if ( g_realismmode - > integer ) {
2024-02-23 23:19:59 +01:00
Event * newev = new Event ( ev - > GetToken ( 1 ) , ev - > NumArgs ( ) - 1 ) ;
2023-07-30 21:21:00 +02:00
for ( int i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
newev - > AddToken ( ev - > GetToken ( i ) ) ;
}
ProcessEvent ( newev ) ;
}
}
2023-08-09 23:09:09 +02:00
void Entity : : EventSPRealismModeCommand ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2024-02-23 23:19:59 +01:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER & & g_realismmode - > integer ) {
Event * newev = new Event ( ev - > GetToken ( 1 ) , ev - > NumArgs ( ) - 1 ) ;
2023-07-30 21:21:00 +02:00
for ( int i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
newev - > AddToken ( ev - > GetToken ( i ) ) ;
}
ProcessEvent ( newev ) ;
}
}
2023-08-09 23:09:09 +02:00
void Entity : : EventDMRealismModeCommand ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2024-02-23 23:19:59 +01:00
if ( g_gametype - > integer ! = GT_SINGLE_PLAYER & & g_realismmode - > integer ) {
Event * newev = new Event ( ev - > GetToken ( 1 ) , ev - > NumArgs ( ) - 1 ) ;
2023-07-30 21:21:00 +02:00
for ( int i = 2 ; i < = ev - > NumArgs ( ) ; i + + ) {
newev - > AddToken ( ev - > GetToken ( i ) ) ;
}
ProcessEvent ( newev ) ;
}
}
2023-08-09 23:09:09 +02:00
void Entity : : GetLocalYawFromVector ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
float yaw ;
Vector vec ;
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
vec = ev - > GetVector ( 1 ) ;
yaw = vectoyaw ( vec ) + 180.0f ;
yaw = AngleSubtract ( yaw , angles [ 1 ] ) ;
ev - > AddFloat ( yaw ) ;
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : EventShootableOnly ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > r . contents | = CONTENTS_SHOOTONLY | CONTENTS_WEAPONCLIP ;
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetShaderTime ( Event * ev )
2023-07-30 21:21:00 +02:00
{
2023-08-09 23:09:09 +02:00
edict - > s . shader_time = level . time ;
if ( ev - > NumArgs ( ) > 0 ) {
edict - > s . shader_time + = ev - > GetFloat ( 1 ) ;
}
2023-07-30 21:21:00 +02:00
2023-08-09 23:09:09 +02:00
if ( ev - > NumArgs ( ) > 1 ) {
edict - > s . shader_time + = ev - > GetFloat ( 1 ) * random ( ) / 32768.0 ;
}
2023-07-30 21:21:00 +02:00
}
2023-08-09 23:09:09 +02:00
qboolean Entity : : GetTagPositionAndOrientation ( str tagname , orientation_t * new_or )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int tagnum ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
tagnum = gi . Tag_NumForName ( edict - > tiki , tagname ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( tagnum < 0 ) {
return false ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
GetTagPositionAndOrientation ( tagnum , new_or ) ;
return true ;
2023-08-03 21:44:16 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : NoTarget ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
if ( ev - > GetBoolean ( 1 ) ) {
flags | = FL_NOTARGET ;
} else {
flags & = ~ FL_NOTARGET ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : GetZone ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2024-09-15 00:42:35 +02:00
ev - > AddInteger ( edict - > r . areanum ) ;
// FIXME: Implement OPM feature
2023-08-09 23:09:09 +02:00
STUB ( ) ;
2016-03-27 11:49:47 +02:00
#if 0
ZoneInfo * zone = getZone ( ) ;
if ( zone ! = NULL ) {
ev - > AddListener ( zone ) ;
} else {
ev - > AddNil ( ) ;
}
# endif
}
2023-08-09 23:09:09 +02:00
void Entity : : IsInZone ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2024-09-15 00:42:35 +02:00
if ( edict - > r . areanum = = ev - > GetInteger ( 1 ) ) {
ev - > AddInteger ( 1 ) ;
} else {
ev - > AddInteger ( 0 ) ;
}
// FIXME: Implement OPM feature
2023-08-09 23:09:09 +02:00
STUB ( ) ;
2016-03-27 11:49:47 +02:00
#if 0
ZoneInfo * zone = ( ZoneInfo * ) ev - > GetEntity ( 1 ) ;
ZoneInfo * currentZone = getZone ( ) ;
if ( zone = = NULL ) {
ScriptError ( " The zone must be a valid ZoneInfo!!! \n " ) ;
}
if ( ! zone - > inheritsFrom ( " ZoneInfo " ) ) {
ScriptError ( " The specified zone is not a ZoneInfo!!! \n " ) ;
}
if ( currentZone = = zone | | IsTouching ( zone ) ) {
ev - > AddInteger ( 1 ) ; // The entity is in the specified zone
} else {
ev - > AddInteger ( 0 ) ; // The entity is not in the specified zone
}
# endif
}
2023-08-09 23:09:09 +02:00
void Entity : : SetDepthHack ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
int bEnable ;
Entity * entity = ( Entity * ) this ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
bEnable = ev - > GetInteger ( 1 ) ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( bEnable ) {
entity - > edict - > s . renderfx | = RF_DEPTHHACK ;
} else {
entity - > edict - > s . renderfx & = ~ RF_DEPTHHACK ;
}
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : ProcessHint ( gentity_t * client , bool bShow )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
Player * player = ( Player * ) client - > entity ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( client - > client ! = NULL ) {
qboolean is_hidden = bShow & & ( edict - > s . renderfx & RF_INVISIBLE ) ;
qboolean can_see = bShow
& & player - > canUse (
this , m_bHintRequiresLookAt
) ; //( player->IsTouching( this ) || player->CanSee( this, string->fov, 94 ) == 1 );
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( bShow & & can_see & & ! is_hidden & & ! player - > IsDead ( ) & & ! player - > IsSpectator ( ) ) {
2023-08-10 11:55:20 +02:00
if ( sv_specialgame - > integer ) {
2023-08-09 23:09:09 +02:00
// FIXME: delete
/*
2017-06-08 11:46:08 +02:00
gi . MSG_SetClient ( client - g_entities ) ;
// Send the hint string once
gi . MSG_StartCGM ( CGM_HINTSTRING ) ;
gi . MSG_WriteString ( m_HintString ) ;
gi . MSG_EndCGM ( ) ;
2023-05-23 00:08:12 +02:00
*/
2023-08-09 23:09:09 +02:00
}
} else {
}
}
2017-06-08 11:46:08 +02:00
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
void Entity : : SetHintRequireLookAt ( Event * ev )
2017-06-08 11:46:08 +02:00
{
2023-08-09 23:09:09 +02:00
m_bHintRequiresLookAt = ev - > GetBoolean ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetHintString ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
m_HintString = ev - > GetString ( 1 ) ;
2016-03-27 11:49:47 +02:00
}
2023-08-09 23:09:09 +02:00
void Entity : : SetShader ( Event * ev )
2016-03-27 11:49:47 +02:00
{
2023-08-09 23:09:09 +02:00
str shadername = ev - > GetString ( 1 ) ;
qboolean fReset = false ;
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
if ( ! shadername . length ( ) ) {
shadername = " default " ;
fReset = true ;
}
2016-03-27 11:49:47 +02:00
2023-08-09 23:09:09 +02:00
gi . SendServerCommand ( - 1 , " setshader %d %s %d " , entnum , shadername . c_str ( ) , fReset ) ;
2016-03-27 11:49:47 +02:00
}
2023-09-02 23:51:37 +02:00
void Entity : : PlayNonPvsSound ( const str & soundName , float volume )
{
AliasListNode_t * ret ;
str name ;
2024-02-25 18:43:42 +01:00
if ( g_gametype - > integer = = GT_SINGLE_PLAYER ) {
// Ignore in single-player
return ;
}
2023-09-02 23:51:37 +02:00
if ( edict - > r . num_nonpvs_sounds > = MAX_NONPVS_SOUNDS ) {
return ;
}
name = GetRandomAlias ( soundName , & ret ) ;
2023-10-02 12:13:22 +02:00
if ( name . length ( ) & & ret ) {
2023-09-02 23:51:37 +02:00
edict - > r . nonpvs_sounds [ edict - > r . num_nonpvs_sounds ] . index = gi . soundindex ( name . c_str ( ) , ret - > streamed ) ;
edict - > r . nonpvs_sounds [ edict - > r . num_nonpvs_sounds ] . volume = G_Random ( ) * ret - > volumeMod + ret - > volume * volume ;
edict - > r . nonpvs_sounds [ edict - > r . num_nonpvs_sounds ] . minDist = ret - > dist ;
edict - > r . nonpvs_sounds [ edict - > r . num_nonpvs_sounds ] . maxDist = ret - > maxDist ;
edict - > r . nonpvs_sounds [ edict - > r . num_nonpvs_sounds ] . pitch = G_Random ( ) * ret - > pitchMod + ret - > pitch ;
edict - > r . num_nonpvs_sounds + + ;
}
}