2023-04-30 00:02:16 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2023 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
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// DESCRIPTION:
|
|
|
|
// Client side command events. These are in the .TIK files and
|
|
|
|
// are processed when the animation specifies it to.
|
|
|
|
|
|
|
|
#include "cg_commands.h"
|
2023-05-06 23:37:05 +02:00
|
|
|
#include "cg_specialfx.h"
|
2023-04-30 20:20:58 +02:00
|
|
|
#include "scriptexception.h"
|
|
|
|
#include "tiki.h"
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
refEntity_t *current_entity = NULL;
|
|
|
|
int current_entity_number = -1;
|
|
|
|
centity_t *current_centity = NULL;
|
|
|
|
float current_scale = -1;
|
2023-04-30 14:47:18 +02:00
|
|
|
dtiki_t* current_tiki = nullptr;
|
2023-04-30 00:02:16 +02:00
|
|
|
cvar_t *cg_showtempmodels;
|
|
|
|
cvar_t *cg_showemitters;
|
|
|
|
cvar_t *cg_physics_fps;
|
|
|
|
cvar_t *cg_detail;
|
|
|
|
cvar_t *cg_effectdetail;
|
2023-05-01 17:06:15 +02:00
|
|
|
cvar_t *cg_effect_physicsrate;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
Vector last_trace_end;
|
|
|
|
|
|
|
|
void CacheResource( const char * stuff );
|
|
|
|
|
|
|
|
ClientGameCommandManager commandManager;
|
|
|
|
|
|
|
|
Event EV_Client_StartBlock
|
|
|
|
(
|
|
|
|
"(",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Signals the beginning of a block of commands"
|
|
|
|
);
|
|
|
|
Event EV_Client_EndBlock
|
|
|
|
(
|
|
|
|
")",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Signals the end of a block of commands"
|
|
|
|
);
|
|
|
|
Event EV_Client_EmitterStartOff
|
|
|
|
(
|
|
|
|
"startoff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Signals an emitter to start in the off state (no tempmodels are emitted)"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAlpha
|
|
|
|
(
|
|
|
|
"alpha",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"alpha",
|
|
|
|
"Set the alpha of the spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetDieTouch
|
|
|
|
(
|
|
|
|
"dietouch",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the spawned tempmodels to die when they touch a solid"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBounceFactor
|
|
|
|
(
|
|
|
|
"bouncefactor",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"factor",
|
|
|
|
"Set the bounciness of a tempmodel when it hits a solid.\n"
|
|
|
|
"A factor > 1 will make the model bounce higher and higher on each hit"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBounceSound
|
|
|
|
(
|
|
|
|
"bouncesound",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sF",
|
|
|
|
"sound [delay]",
|
|
|
|
"When bouncing, what sound to play on impact and an option delay (default is 1 second) between playing this sound"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBounceSoundOnce
|
|
|
|
(
|
|
|
|
"bouncesoundonce",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"sound",
|
|
|
|
"When bouncing, what sound to play on impact one time"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetScale
|
|
|
|
(
|
|
|
|
"scale",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"scale",
|
|
|
|
"Set the scale of a spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetScaleUpDown
|
|
|
|
(
|
|
|
|
"scaleupdown",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodel to scale up to scale value and then down."
|
|
|
|
);
|
|
|
|
Event EV_Client_SetScaleMin
|
|
|
|
(
|
|
|
|
"scalemin",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"scalemin",
|
|
|
|
"Set the minimum scale of a spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetScaleMax
|
|
|
|
(
|
|
|
|
"scalemax",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"scalemax",
|
|
|
|
"Set the maximum scale of a spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetModel
|
|
|
|
(
|
|
|
|
"model",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sSSSSS",
|
|
|
|
"modelname1 modelname2 modelname3 modelname4 modelname5 modelname6",
|
|
|
|
"Set the modelname of the tempmodel. If more than 1 model is specified, it will\n"
|
|
|
|
"be randomly chosen when spawned"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetLife
|
|
|
|
(
|
|
|
|
"life",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"life",
|
|
|
|
"Set the life (in seconds) of the spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetColor
|
|
|
|
(
|
|
|
|
"color",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fffF",
|
|
|
|
"red green blue alpha",
|
|
|
|
"Set the color (modulate) of the spawned tempmodel."
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_SetRadialVelocity
|
|
|
|
(
|
|
|
|
"radialvelocity",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"scale min_additional max_additional",
|
|
|
|
"Subtracts the particle origin from origin and multiplies by scale, then adds additional velocity\n"
|
|
|
|
"between min and max... negative values bring toward origin\n"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetVelocity
|
|
|
|
(
|
|
|
|
"velocity",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"forwardVelocity",
|
|
|
|
"Set the forward velocity of the spawned tempmodel"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAngularVelocity
|
|
|
|
(
|
|
|
|
"avelocity",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"yawVel pitchVel rollVel",
|
|
|
|
"Set the angular velocity of the spawned tempmodel"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_SetColorVelocity
|
|
|
|
(
|
|
|
|
"colorvelocity",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"rVel gVel bVel",
|
|
|
|
"Set the color velocity of the spawned dlight tempmodel"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetRandomVelocity
|
|
|
|
(
|
|
|
|
"randvel",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"SfFSfFSfF",
|
|
|
|
"[random|crandom|range] xVel [xVel2] [random|crandom|range] yVel [yVel2] [random|crandom|range] zVel [zVel2]",
|
2023-04-30 00:02:16 +02:00
|
|
|
"Add a random component to the regular velocity.\n"
|
|
|
|
"If random is specified, the component will range from 0 to specified velocity.\n"
|
|
|
|
"If crandom is specified, the component will range from -specified to +specified velocity.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"If range is specified, the component needs two values; it will randomly pick a number in the range\n"
|
|
|
|
"from the first number to the first number plus the second number.\n"
|
|
|
|
"If no keyword is explicitly specified, then the component will just be added on\n"
|
|
|
|
"without randomness.\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
"This velocity is applied using the world axis"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetRandomVelocityAlongAxis
|
|
|
|
(
|
|
|
|
"randvelaxis",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"SfFSfFSfF",
|
|
|
|
"[random|crandom|range] forwardVel [forwardVel2] [random|crandom|range] rightVel [rightVel2] [random|crandom|rang"
|
|
|
|
"e] upVel [upVel2]",
|
2023-04-30 00:02:16 +02:00
|
|
|
"Add a random component to the regular velocity.\n"
|
|
|
|
"If random is specified, the component will range from 0 to specified velocity.\n"
|
|
|
|
"If crandom is specified, the component will range from -specified to +specified velocity.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"If range is specified, the component needs two values; it will randomly pick a number in the range\n"
|
|
|
|
"from the first number to the first number plus the second number.\n"
|
|
|
|
"If no keyword is explicitly specified, then the component will just be added on\n"
|
|
|
|
"without randomness.\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
"This velocity is applied using the parent axis"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAccel
|
|
|
|
(
|
|
|
|
"accel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"xAcc yAcc zAcc",
|
|
|
|
"Set the acceleration of the spawned tempmodel.\n"
|
|
|
|
"This acceleration is applied using the world axis"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_SetFriction
|
|
|
|
(
|
|
|
|
"friction",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"friction",
|
|
|
|
"Set the friction as a fraction of velocity per second... exact effect depends on physics rate:\n"
|
|
|
|
"slowdown per second = [1 - (friction / physicsrate)] ^ physicsrate; physicsrate defaults to 10"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetVaryColor
|
|
|
|
(
|
|
|
|
"varycolor",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Sets the color to vary by 0 to -20% of specified color"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetSmokeParms
|
|
|
|
(
|
|
|
|
"smokeparms",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"typeinfo fademult scalemult",
|
|
|
|
"Sets some misc parms for smoke"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetCount
|
|
|
|
(
|
|
|
|
"count",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"count",
|
|
|
|
"Set the number of tempmodels that are spawned\n"
|
|
|
|
"This is only used for the originspawn and tagspawn commands,\n"
|
|
|
|
"and not for emitters, use spawnrate instead"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetFade
|
|
|
|
(
|
|
|
|
"fade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodel to fade out over it's life"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetFadeDelay
|
|
|
|
(
|
|
|
|
"fadedelay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"time",
|
|
|
|
"Set the amount of time to delay a fade"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetFadeIn
|
|
|
|
(
|
|
|
|
"fadein",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"time",
|
|
|
|
"Set the tempmodel to fade in over the specified time"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetTwinkle
|
|
|
|
(
|
|
|
|
"twinkle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ffff",
|
|
|
|
"mintimeoff maxtimeoff mintimeon maxtimeon",
|
|
|
|
"Set the tempmodel to twinkle with the specified settings"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetTrail
|
|
|
|
(
|
|
|
|
"trail",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sssf",
|
|
|
|
"shader startTag endTag life",
|
|
|
|
"Set the tempmodel to have a swipe that follows it"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_SetSpawnRange
|
|
|
|
(
|
|
|
|
"spawnrange",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"iI",
|
|
|
|
"range1 range2",
|
|
|
|
"Sets the range in which this effect will spawn tempmodels. If one number is specified, it is the max range\n"
|
|
|
|
"and 0 is the min range; if two numbers are specified, the larger is the max range.\n"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetSpawnRate
|
|
|
|
(
|
|
|
|
"spawnrate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"rate",
|
|
|
|
"Set the spawnrate of the emitter (models per second).\n"
|
|
|
|
"This is only used for emitters and not for the originspawn and tagspawn commands"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetOriginOffset
|
|
|
|
(
|
|
|
|
"offset",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"SfFSfFSfF",
|
|
|
|
"[random|crandom|range] offsetX [offsetX2] [random|crandom|range] offsetY [offsetY2] [random|crandom|range] offsetZ [offsetZ2]",
|
2023-04-30 00:02:16 +02:00
|
|
|
"If random is specified, the component will range from 0 to +specified offset.\n"
|
|
|
|
"If crandom is specified, the component will range from -specified to +specified offset.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"If range is specified, the component needs two values; it will randomly pick a number in the range\n"
|
|
|
|
"from the first number to the first number plus the second number.\n"
|
|
|
|
"If no keyword is explicitly specified, then the component will just be added on\n"
|
|
|
|
"without randomness.\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
"This offset is applied using the world axis."
|
|
|
|
);
|
|
|
|
Event EV_Client_SetScaleRate
|
|
|
|
(
|
|
|
|
"scalerate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"rate",
|
|
|
|
"Set the scaling rate of the spawned tempmodel\n"
|
|
|
|
"If a negative rate is used, the model will shrink"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetCircle
|
|
|
|
(
|
|
|
|
"circle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels to be spawned in a circle around the origin\n"
|
|
|
|
"This circle will be generated in the X/Y axis of the model"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetSphere
|
|
|
|
(
|
|
|
|
"sphere",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels to spawn in a sphere around the origin.\n"
|
|
|
|
"If sphereradius is set, the tempmodels will spawn at the radius distance from\n"
|
|
|
|
"the origin"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetInwardSphere
|
|
|
|
(
|
|
|
|
"inwardsphere",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Create the tempmodels in a sphere around the origin, and adjust their\n"
|
|
|
|
"angle so they point toward the center of the sphere. This is best used with a\n"
|
|
|
|
"spehere radius and some velocity so the models look like they're heading toward the\n"
|
|
|
|
"center of the sphere."
|
|
|
|
);
|
|
|
|
Event EV_Client_SetRadius
|
|
|
|
(
|
|
|
|
"radius",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"Set the radius of the sphere for the inwardsphere amd sphere settings"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetSwarm
|
|
|
|
(
|
|
|
|
"swarm",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"iff",
|
|
|
|
"frequency maxspeed delta",
|
|
|
|
"Create a swarm like effect that the tempmodels follow when they are spawned\n"
|
|
|
|
"frequency is how often they change direction\n"
|
|
|
|
"maxspeed is how fast the tempmodel will move (it's randomly generated every\n"
|
|
|
|
"time the frequency is hit\n"
|
|
|
|
"delta is how much the tempmodel moves toward the origin every frame"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetWavy
|
|
|
|
(
|
|
|
|
"wavy",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"SF",
|
|
|
|
"[random|crandom] distance",
|
|
|
|
"Set the tempmodel to move in a wavy path to a maxmimun of the distance specified\n"
|
|
|
|
"If random is specified, the distance is between 0 and +specified distance\n"
|
|
|
|
"If crandom is specified, the distance is between -specified and +specified distance"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAlign
|
|
|
|
(
|
|
|
|
"align",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Align the tempmodels to the direction they are traveling"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAlignOnce
|
|
|
|
(
|
|
|
|
"alignonce",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Align the tempmodels to the direction they are traveling at the time they are initialized"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetFlickerAlpha
|
|
|
|
(
|
|
|
|
"flicker",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodel to change it's alpha every frame. Creates a flickering effect"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetCollision
|
|
|
|
(
|
|
|
|
"collision",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"S",
|
|
|
|
"water",
|
|
|
|
"Turn on collision for the tempmodel.\n"
|
|
|
|
"If the keyword water is specified, then the tempmodel will collide with water"
|
|
|
|
);
|
|
|
|
Event EV_Client_TagSpawn
|
|
|
|
(
|
|
|
|
"tagspawn",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"tagName",
|
|
|
|
"Spawn tempmodels from the specified tag.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the tempmodels"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_TagSpawnLinked
|
|
|
|
(
|
|
|
|
"tagspawnlinked",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"tagName",
|
|
|
|
"Spawn tempmodels from the specified tag, linked to the entity at the tag.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the tempmodels"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_OriginSpawn
|
|
|
|
(
|
|
|
|
"originspawn",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Spawn tempmodels from the origin.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the tempmodels"
|
|
|
|
);
|
|
|
|
Event EV_Client_OriginBeamSpawn
|
|
|
|
(
|
|
|
|
"originbeamspawn",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Spawn a beam from the origin.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_OriginBeamEmitter
|
|
|
|
(
|
|
|
|
"originbeamemitter",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Spawn beams from the origin.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_TagEmitter
|
|
|
|
(
|
|
|
|
"tagemitter",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ss",
|
|
|
|
"tagName emitterName",
|
|
|
|
"Create an emitter that spawns tempmodels from the specified tag.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the tempmodels"
|
|
|
|
);
|
|
|
|
Event EV_Client_OriginEmitter
|
|
|
|
(
|
|
|
|
"originemitter",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"emitterName",
|
|
|
|
"Create an emitter that spawns tempmodels from the origin.\n"
|
|
|
|
"This command is followed by a ( to specify a block of commands that modify the tempmodels"
|
|
|
|
);
|
|
|
|
Event EV_Client_EmitterOn
|
|
|
|
(
|
|
|
|
"emitteron",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"emitterName",
|
|
|
|
"Turn the specified emitter on"
|
|
|
|
);
|
|
|
|
Event EV_Client_EmitterOff
|
|
|
|
(
|
|
|
|
"emitteroff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"emitterName",
|
|
|
|
"Turn the specified emitter off"
|
|
|
|
);
|
|
|
|
Event EV_Client_Sound
|
|
|
|
(
|
|
|
|
"sound",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"sSFFFFS",
|
|
|
|
"soundName channelName volume min_distance pitch randompitch randomvolume argstype",
|
2023-04-30 00:02:16 +02:00
|
|
|
"Play the specified sound"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Set_Current_Tiki
|
|
|
|
(
|
|
|
|
"sound",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"settiki tikiname - all subsequent events are applied to this tiki",
|
|
|
|
"sets the tiki the aliases should be on in the sound uberfile"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_StopSound
|
|
|
|
(
|
|
|
|
"stopsound",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"channel",
|
|
|
|
"Stops the sound on the specified channel."
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_StopAliasChannel
|
|
|
|
(
|
|
|
|
"stopaliaschannel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"alias",
|
|
|
|
"Stops the sound channel used by the specified alias."
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_LoopSound
|
|
|
|
(
|
|
|
|
"loopsound",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"sFFf",
|
|
|
|
"soundName volume min_distance pitch",
|
2023-04-30 00:02:16 +02:00
|
|
|
"Play the specifed sound as a looping sound"
|
|
|
|
);
|
|
|
|
Event EV_Client_Cache
|
|
|
|
(
|
|
|
|
"cache",
|
2023-05-05 23:43:27 +02:00
|
|
|
EV_CACHE,
|
|
|
|
"s",
|
|
|
|
"resourceName",
|
|
|
|
"Cache the specified resource"
|
|
|
|
);
|
|
|
|
Event EV_Client_CacheImage
|
|
|
|
(
|
|
|
|
"cacheimage",
|
|
|
|
EV_CACHE,
|
|
|
|
"s",
|
|
|
|
"imageName",
|
|
|
|
"Cache the specified image (For menu graphics that should never be picmiped)"
|
|
|
|
);
|
|
|
|
Event EV_Client_CacheFont
|
|
|
|
(
|
|
|
|
"cachefont",
|
|
|
|
EV_CACHE,
|
2023-04-30 00:02:16 +02:00
|
|
|
"s",
|
|
|
|
"resourceName",
|
|
|
|
"Cache the specified resource"
|
|
|
|
);
|
|
|
|
Event EV_Client_AliasCache
|
|
|
|
(
|
|
|
|
"aliascache",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ssSSSSSS",
|
|
|
|
"alias realPath arg1 arg2 arg3 arg4 arg5 arg6",
|
|
|
|
"Create an alias to the specified path and cache the resource"
|
|
|
|
);
|
|
|
|
Event EV_Client_Alias
|
|
|
|
(
|
|
|
|
"alias",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ssSSSSSS",
|
|
|
|
"alias realPath arg1 arg2 arg3 arg4 arg5 arg6",
|
|
|
|
"Create an alias to the specified path"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_CacheAlias
|
|
|
|
(
|
|
|
|
"cachefromalias",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"alias",
|
|
|
|
"Caches all data matching a previously specified alias"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_Footstep
|
|
|
|
(
|
|
|
|
"footstep",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"ssI",
|
|
|
|
"tag sRunning iEquipment",
|
|
|
|
"Play a footstep sound that is appropriate to the surface we are currently stepping on\n"
|
|
|
|
"sRunning should be set to run, walk, or ladder"
|
|
|
|
);
|
|
|
|
Event EV_Client_Landing
|
|
|
|
(
|
|
|
|
"footstep",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"FI",
|
|
|
|
"fVolume iEquipment",
|
|
|
|
"Play a landing sound that is appropriate to the surface we are landing on\n"
|
|
|
|
);
|
|
|
|
Event EV_Client_BodyFall
|
|
|
|
(
|
|
|
|
"bodyfall",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"F",
|
|
|
|
"fVolume",
|
|
|
|
"Play a body fall sound that is appropriate to the surface we are falling on\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
);
|
|
|
|
Event EV_Client_Client
|
|
|
|
(
|
|
|
|
"client",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"SSSSSS",
|
|
|
|
"arg1 arg2 arg3 arg4 arg5 arg6",
|
|
|
|
"Execute the specified command arg string"
|
|
|
|
);
|
|
|
|
Event EV_Client_OriginDynamicLight
|
|
|
|
(
|
|
|
|
"origindlight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fffffSS",
|
|
|
|
"red green blue intensity life type1 type2",
|
|
|
|
"Spawn a dynamic light from the origin of the model\n"
|
|
|
|
"The red,green,blue parms are the color of the light\n"
|
|
|
|
"The intensity is the radius of the light\n"
|
|
|
|
"type is the type of light to create (lensflare,viewlensflare,additive)"
|
|
|
|
);
|
|
|
|
Event EV_Client_TagDynamicLight
|
|
|
|
(
|
|
|
|
"tagdlight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sfffffSS",
|
|
|
|
"tagName red green blue intensity life type1 type2",
|
|
|
|
"Spawn a dynamic light from the specified tag\n"
|
|
|
|
"The red,green,blue parms are the color of the light\n"
|
|
|
|
"The intensity is the radius of the light\n"
|
|
|
|
"type is the type of light to create (lensflare,viewlensflare,additive)"
|
|
|
|
);
|
|
|
|
Event EV_Client_DynamicLight
|
|
|
|
(
|
|
|
|
"dlight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ffffSS",
|
|
|
|
"red green blue intensity type1 type2",
|
|
|
|
"This makes the emitter itself a dynamic light"
|
|
|
|
"The red,green,blue parms are the color of the light\n"
|
|
|
|
"The intensity is the radius of the light\n"
|
|
|
|
"type is the type of light to create (lensflare,viewlensflare,additive)"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_BlockDynamicLight
|
|
|
|
(
|
|
|
|
"blockdlight",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ffSS",
|
|
|
|
"intensity life type1 type2",
|
|
|
|
"Spawn a dynamic light from the origin of the model\n"
|
|
|
|
"An additional commands block allows the specification of moving & varying dlights\n"
|
|
|
|
"The intensity is the radius of the light\n"
|
|
|
|
"type is the type of light to create (lensflare,viewlensflare,additive)"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetEntityColor
|
|
|
|
(
|
|
|
|
"entcolor",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fffF",
|
|
|
|
"red green blue alpha",
|
|
|
|
"Set the color(modulate) of this entity"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetTexAnimTime
|
|
|
|
(
|
|
|
|
"texanimtime",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"time",
|
|
|
|
"Set the texture animation speed"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetGlobalFade
|
|
|
|
(
|
|
|
|
"globalfade",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"S",
|
|
|
|
"[in|out]",
|
|
|
|
"Set the tempmodels to globally fade in or out together"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetParentLink
|
|
|
|
(
|
|
|
|
"parentlink",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels linked to the parent, so they move with the parent model"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetHardLink
|
|
|
|
(
|
|
|
|
"hardlink",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels linked to the model they are spawned from, so they move with it"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetRandomRoll
|
|
|
|
(
|
|
|
|
"randomroll",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels so they pick a random roll value every frame"
|
|
|
|
);
|
|
|
|
Event EV_Client_ParentAngles
|
|
|
|
(
|
|
|
|
"parentangles",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the tempmodels angles to that of its parent"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_EmitterAngles
|
|
|
|
(
|
|
|
|
"emitterangles",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"FFF",
|
|
|
|
"pitchofs yawofs rollofs",
|
|
|
|
"Set the tempmodels angles to that of the emitter\n"
|
|
|
|
"The three optional parameters are for setting an angle offset from the emitter"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetAngles
|
|
|
|
(
|
|
|
|
"angles",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"SfFSfFSfF",
|
|
|
|
"[random|crandom|range] pitch [pitch2] [random|crandom|range] yaw [yaw2] [random|crandom|range] roll [roll2]",
|
2023-04-30 00:02:16 +02:00
|
|
|
"If random is specified, the component will range from 0 to +specified value.\n"
|
|
|
|
"If crandom is specified, the component will range from -specified to +specified value.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"If range is specified, the component needs two values; it will randomly pick a number in the range\n"
|
|
|
|
"from the first number to the first number plus the second number.\n"
|
|
|
|
"If no keyword is explicitly specified, then the component will be just set\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
);
|
|
|
|
Event EV_Client_Swipe
|
|
|
|
(
|
|
|
|
"swipe",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"V",
|
|
|
|
"origin",
|
|
|
|
"Do a swipe and add it on to the swipe rendering list."
|
|
|
|
);
|
|
|
|
Event EV_Client_SwipeOn
|
|
|
|
(
|
|
|
|
"swipeon",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ssff",
|
|
|
|
"shader startTagName endTagNamelife life",
|
|
|
|
"Signal the start of a swipe from the current tag"
|
|
|
|
);
|
|
|
|
Event EV_Client_SwipeOff
|
|
|
|
(
|
|
|
|
"swipeoff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Signal the end of a swipe"
|
|
|
|
);
|
|
|
|
Event EV_Client_BeginTagBeamEmitter
|
|
|
|
(
|
|
|
|
"tagbeamemitter",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sss",
|
|
|
|
"tagstart tagend name",
|
|
|
|
"Create a beam emitter that uses 2 tags to determine it's start and end position"
|
|
|
|
);
|
|
|
|
Event EV_Client_BeginTagBeamSpawn
|
|
|
|
(
|
|
|
|
"tagbeamspawn",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sf",
|
|
|
|
"tagstart name",
|
|
|
|
"Create a beam emitter that uses the tag to determine it's starting position."
|
|
|
|
);
|
|
|
|
Event EV_Client_AnimateOnce
|
|
|
|
(
|
|
|
|
"animateonce",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set a tempmodel to animate once and then get removed"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAnim
|
|
|
|
(
|
|
|
|
"anim",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"animation",
|
|
|
|
"Set a tempmodel the the specified animation"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetSubdivisions
|
|
|
|
(
|
|
|
|
"numsegments",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"numsegments",
|
|
|
|
"Set the number of segments in a beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetMinOffset
|
|
|
|
(
|
|
|
|
"minoffset",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"minoffset",
|
|
|
|
"Set the minimum offset from center in a beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetMaxOffset
|
|
|
|
(
|
|
|
|
"maxoffset",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"maxoffset",
|
|
|
|
"Set the maximum offset from center in a beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamShader
|
|
|
|
(
|
|
|
|
"beamshader",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"shadername",
|
|
|
|
"Set the shader to use for the beam"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamLength
|
|
|
|
(
|
|
|
|
"beamlength",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"length",
|
|
|
|
"Set the length of the beam or trace length (for decals)"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamDelay
|
|
|
|
(
|
|
|
|
"beamdelay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"SF",
|
|
|
|
"[random] delay",
|
|
|
|
"Set the delay time between creating new beams.\n"
|
|
|
|
"If the keyword random is specified, the delay between beams will occur randomly between 0 and the time specified"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamToggleDelay
|
|
|
|
(
|
|
|
|
"beamtoggledelay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"SF",
|
|
|
|
"[random] delay",
|
|
|
|
"Set a delay between toggling the beams on and off.\n"
|
|
|
|
"If the keyword random is specified, the delay between toggling will occur randomly between 0 and the time specified"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamPersist
|
|
|
|
(
|
|
|
|
"beampersist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Make the beams persist instead of blinking out"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetBeamOffsetEndpoints
|
|
|
|
(
|
|
|
|
"beam_offset_endpoints",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Make the beams endpoints offset to reduce the bunching up effect"
|
|
|
|
);
|
|
|
|
Event EV_Client_BeamSphere
|
|
|
|
(
|
|
|
|
"beamsphere",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"i",
|
|
|
|
"count",
|
|
|
|
"Create a sphere shaped beam effect from the origin. Count is the number of beams"
|
|
|
|
);
|
|
|
|
Event EV_Client_Spread
|
|
|
|
(
|
|
|
|
"spread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ff",
|
|
|
|
"spreadx spready",
|
|
|
|
"Add a random variance in the spawned beam in the forward direction by the amound specified in spreadx and spready"
|
|
|
|
);
|
|
|
|
Event EV_Client_UseLastTraceEnd
|
|
|
|
(
|
|
|
|
"uselasttraceend",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Makes this trace command use the end results of the last trace command"
|
|
|
|
);
|
|
|
|
Event EV_Client_OffsetAlongAxis
|
|
|
|
(
|
|
|
|
"offsetalongaxis",
|
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"SfFSfFSfF",
|
|
|
|
"[crandom|random|range] offsetx [offsetx2] [crandom|random|range] offsety [offsety2] [crandom|random|range] offsetz [offsetz2]",
|
2023-04-30 00:02:16 +02:00
|
|
|
"If random is specified, the component will range from 0 to specified offset.\n"
|
|
|
|
"If crandom is specified, the component will range from -specified to +specified offset.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"If range is specified, the component needs two values; it will randomly pick a number in the range\n"
|
|
|
|
"from the first number to the first number plus the second number.\n"
|
|
|
|
"If no keyword is explicitly specified, then the component will just be added on\n"
|
|
|
|
"without randomness.\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
"This offset is applied using the model's local axis"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_Cone
|
|
|
|
(
|
|
|
|
"cone",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ff",
|
|
|
|
"height radius",
|
|
|
|
"Randomly spawns the particle somewhere inside a cone along the model's local x axis"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_SetEndAlpha
|
|
|
|
(
|
|
|
|
"endalpha",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"alpha",
|
|
|
|
"Set the alpha of the beam's endpoint"
|
|
|
|
);
|
|
|
|
Event EV_Client_RandomChance
|
|
|
|
(
|
|
|
|
"randomchance",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fSSSSSS",
|
|
|
|
"percentage [arg1] [arg2] [arg3] [arg4] [arg5] [arg6]",
|
|
|
|
"Set the percentage chance that command will occur"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_DelayedRepeat
|
2023-04-30 00:02:16 +02:00
|
|
|
(
|
2023-05-05 23:43:27 +02:00
|
|
|
"delayedrepeat",
|
2023-04-30 00:02:16 +02:00
|
|
|
EV_DEFAULT,
|
|
|
|
"fiSSSSSS",
|
|
|
|
"time commandnumber [arg1] [arg2] [arg3] [arg4] [arg5] [arg6]",
|
|
|
|
"Set the time delay between this command getting executed. This requires a command number to be assigned here.\n"
|
2023-05-05 23:43:27 +02:00
|
|
|
"This is internally used to keep track of the commands this entity executes and will resolve naming conflicts.\n"
|
|
|
|
"This is only useful if the command gets called continuously but must execute at regular intervals.\n"
|
2023-04-30 00:02:16 +02:00
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_CommandDelay
|
2023-04-30 00:02:16 +02:00
|
|
|
(
|
2023-05-05 23:43:27 +02:00
|
|
|
"commanddelay",
|
2023-04-30 00:02:16 +02:00
|
|
|
EV_DEFAULT,
|
2023-05-05 23:43:27 +02:00
|
|
|
"fiSSSSSS",
|
|
|
|
"time commandnumber [arg1] [arg2] [arg3] [arg4] [arg5] [arg6]",
|
|
|
|
"Set the time delay between this command getting executed. This requires a command number to be assigned here.\n"
|
|
|
|
"This is internally used to keep track of the commands this entity executes and will resolve naming conflicts."
|
2023-04-30 00:02:16 +02:00
|
|
|
);
|
|
|
|
Event EV_Client_BounceDecal
|
|
|
|
(
|
|
|
|
"bouncedecal",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"iI",
|
|
|
|
"maxamount temporary",
|
|
|
|
"Put a mark when the tempmodel bounces and hits a surface\n"
|
|
|
|
"maxamount = Max amount of decals to make when bouncing\n"
|
|
|
|
"temporary = specify 1 for a temporary mark that only appears for a short time, 0 for a decal that stays aroung longer (default is 0)\n"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetDecalRadius
|
|
|
|
(
|
|
|
|
"decalradius",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"radius",
|
|
|
|
"Set the radius of the decal"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetDecalOrientation
|
|
|
|
(
|
|
|
|
"orientation",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"degrees",
|
|
|
|
"Set the degrees to orient the decal. Specify 'random' to use a random orientation"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetDecalShader
|
|
|
|
(
|
|
|
|
"decalshader",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"shadername",
|
|
|
|
"Set the shader to use for the impact decal"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetTraceLength
|
|
|
|
(
|
|
|
|
"tracelength",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"length",
|
|
|
|
"Set the length of the trace for the decal"
|
|
|
|
);
|
|
|
|
Event EV_Client_TraceSpawn
|
|
|
|
(
|
|
|
|
"tracespawn",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"modelname",
|
|
|
|
"Spawn the specified model when the trace hits a solid object"
|
|
|
|
);
|
|
|
|
Event EV_Client_TagList
|
|
|
|
(
|
|
|
|
"taglist",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ssSSSSSS",
|
|
|
|
"arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8",
|
|
|
|
"Set the tag list to create a beam that travels between all the tags"
|
|
|
|
);
|
|
|
|
Event EV_Client_Lightstyle
|
|
|
|
(
|
|
|
|
"lightstyle",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"nameOfImage",
|
|
|
|
"Set a lightstyle to determine the color of this tempmodel, the image\n"
|
|
|
|
"specified is used to determine the look of the light style"
|
|
|
|
);
|
|
|
|
Event EV_Client_PhysicsRate
|
|
|
|
(
|
|
|
|
"physicsrate",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"rate",
|
|
|
|
"Set the rate (in updates per second) for the tempmodel's physics to be updated"
|
|
|
|
);
|
|
|
|
Event EV_Client_Parallel
|
|
|
|
(
|
|
|
|
"parallel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set tempmodel to be parallel to the viewer"
|
|
|
|
);
|
2023-05-05 23:43:27 +02:00
|
|
|
Event EV_Client_AlwaysDraw
|
|
|
|
(
|
|
|
|
"alwaysdraw",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set emitter/tempmodel to be alwaysdraw. Which can be turned off by alwaysdraw"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
Event EV_Client_Detail
|
|
|
|
(
|
|
|
|
"detail",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set emitter/tempmodel to be detail. Which can be turned off by detail"
|
|
|
|
);
|
|
|
|
Event EV_Client_Print
|
2023-05-05 23:43:27 +02:00
|
|
|
(
|
|
|
|
"print",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"string",
|
|
|
|
"Prints a string."
|
|
|
|
);
|
|
|
|
Event EV_Client_SetVolumetric
|
|
|
|
(
|
|
|
|
"volumetric",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Set the effect to spawn volumetric sources rather than tempmodels"
|
|
|
|
);
|
|
|
|
Event EV_Client_Wind
|
|
|
|
(
|
|
|
|
"wind",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Makes the temp model be affected by wind"
|
|
|
|
);
|
|
|
|
Event EV_Client_SpriteGridLighting
|
|
|
|
(
|
|
|
|
"spritegridlighting",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Calculates grid lighting for a sprite"
|
|
|
|
);
|
|
|
|
Event EV_Client_WaterOnly
|
|
|
|
(
|
|
|
|
"wateronly",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"makes the temp model remove itself if it leaves water"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetAlignStretch
|
|
|
|
(
|
|
|
|
"alignstretch",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"F",
|
|
|
|
"scaleMultiplier",
|
|
|
|
"Aligns the temp model to the direction of travel, and stretches it betwen the last and current positions.\n"
|
|
|
|
);
|
|
|
|
Event EV_Client_SetClampVelocity
|
|
|
|
(
|
|
|
|
"clampvel",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ffffff",
|
|
|
|
"minX maxX minY maxY minZ maxZ",
|
|
|
|
"sets the valid range for velocities along global axes. Cannot be used with clampvelaxis."
|
|
|
|
);
|
|
|
|
Event EV_Client_SetClampVelocityAxis
|
|
|
|
(
|
|
|
|
"clampvelaxis",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ffffff",
|
|
|
|
"minX maxX minY maxY minZ maxZ",
|
|
|
|
"sets the valid range for velocities along oriented axes. Cannot be used with clampvel."
|
|
|
|
);
|
|
|
|
Event EV_Client_Treads
|
|
|
|
(
|
|
|
|
"treads",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"ssi",
|
|
|
|
"tagName shader localrefnumber",
|
|
|
|
"Spawn treads from the specified tag using the specified tread type."
|
|
|
|
);
|
|
|
|
Event EV_Client_Treads_Off
|
|
|
|
(
|
|
|
|
"treadsoff",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"si",
|
|
|
|
"tagName localrefnumber",
|
|
|
|
"Stops spawning treads from the specified tag."
|
|
|
|
);
|
|
|
|
Event EV_Client_ViewKick
|
|
|
|
(
|
|
|
|
"viewkick",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fffffsff",
|
|
|
|
"pitchmin pitchmax yawmin yawmax recenterspeed patters pitchmax yawmax scatterpitchmax",
|
|
|
|
"Adds kick to the view of the owner when fired."
|
|
|
|
);
|
|
|
|
Event EV_Client_EyeLimits
|
|
|
|
(
|
|
|
|
"eyelimits",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fff",
|
|
|
|
"fPitchmax fYawmax fRollmax",
|
|
|
|
"Set the max angle offsets for the eyes from the model's head"
|
|
|
|
);
|
|
|
|
Event EV_Client_EyeMovement
|
|
|
|
(
|
|
|
|
"eyemovement",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"f",
|
|
|
|
"fMovement",
|
|
|
|
"Sets the amount of the head's movement to apply to the players view. 1 is full, 0 is none"
|
|
|
|
);
|
|
|
|
Event EV_Client_SFXStart
|
|
|
|
(
|
|
|
|
"sfx",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sSSSSSSSS",
|
|
|
|
"sCommand arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8",
|
|
|
|
"Used for adding commands to a special effect"
|
|
|
|
);
|
|
|
|
Event EV_Client_SFXStartDelayed
|
|
|
|
(
|
|
|
|
"delayedsfx",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fsSSSSSSSS",
|
|
|
|
"fDelay sCommand arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8",
|
|
|
|
"Used for adding commands to a special effect with a time delay"
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-06 17:02:40 +02:00
|
|
|
EffectsEventQueueNode EffectsEventQueue;
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
CLASS_DECLARATION( Listener, ClientGameCommandManager, NULL )
|
|
|
|
{
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_StartBlock, &ClientGameCommandManager::StartBlock },
|
|
|
|
{ &EV_Client_EndBlock, &ClientGameCommandManager::EndBlock },
|
|
|
|
{ &EV_Client_EmitterStartOff, &ClientGameCommandManager::EmitterStartOff },
|
|
|
|
{ &EV_Client_OriginSpawn, &ClientGameCommandManager::BeginOriginSpawn },
|
|
|
|
{ &EV_Client_OriginBeamSpawn, &ClientGameCommandManager::BeginOriginBeamSpawn },
|
|
|
|
{ &EV_Client_OriginBeamEmitter, &ClientGameCommandManager::BeginOriginBeamEmitter },
|
|
|
|
{ &EV_Client_TagSpawn, &ClientGameCommandManager::BeginTagSpawn },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_TagSpawnLinked, &ClientGameCommandManager::BeginTagSpawnLinked },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_TagEmitter, &ClientGameCommandManager::BeginTagEmitter },
|
|
|
|
{ &EV_Client_BeginTagBeamEmitter, &ClientGameCommandManager::BeginTagBeamEmitter },
|
|
|
|
{ &EV_Client_BeginTagBeamSpawn, &ClientGameCommandManager::BeginTagBeamSpawn },
|
|
|
|
{ &EV_Client_OriginEmitter, &ClientGameCommandManager::BeginOriginEmitter },
|
|
|
|
{ &EV_Client_EmitterOn, &ClientGameCommandManager::EmitterOn },
|
|
|
|
{ &EV_Client_EmitterOff, &ClientGameCommandManager::EmitterOff },
|
|
|
|
{ &EV_Client_SetAlpha, &ClientGameCommandManager::SetAlpha },
|
|
|
|
{ &EV_Client_SetDieTouch, &ClientGameCommandManager::SetDieTouch },
|
|
|
|
{ &EV_Client_SetBounceFactor, &ClientGameCommandManager::SetBounceFactor },
|
|
|
|
{ &EV_Client_SetBounceSound, &ClientGameCommandManager::SetBounceSound },
|
|
|
|
{ &EV_Client_SetBounceSoundOnce, &ClientGameCommandManager::SetBounceSoundOnce },
|
|
|
|
{ &EV_Client_SetScale, &ClientGameCommandManager::SetScale },
|
|
|
|
{ &EV_Client_SetScaleUpDown, &ClientGameCommandManager::SetScaleUpDown },
|
|
|
|
{ &EV_Client_SetScaleMin, &ClientGameCommandManager::SetScaleMin },
|
|
|
|
{ &EV_Client_SetScaleMax, &ClientGameCommandManager::SetScaleMax },
|
|
|
|
{ &EV_Client_SetModel, &ClientGameCommandManager::SetModel },
|
|
|
|
{ &EV_Client_SetLife, &ClientGameCommandManager::SetLife },
|
|
|
|
{ &EV_Client_SetColor, &ClientGameCommandManager::SetColor },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_SetRadialVelocity, &ClientGameCommandManager::SetRadialVelocity },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetVelocity, &ClientGameCommandManager::SetVelocity },
|
|
|
|
{ &EV_Client_SetAngularVelocity, &ClientGameCommandManager::SetAngularVelocity },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_SetColorVelocity, &ClientGameCommandManager::SetAngularVelocity },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetRandomVelocity, &ClientGameCommandManager::SetRandomVelocity },
|
|
|
|
{ &EV_Client_SetRandomVelocityAlongAxis, &ClientGameCommandManager::SetRandomVelocityAlongAxis },
|
|
|
|
{ &EV_Client_SetAccel, &ClientGameCommandManager::SetAccel },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_SetFriction, &ClientGameCommandManager::SetFriction },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetCount, &ClientGameCommandManager::SetCount },
|
|
|
|
{ &EV_Client_SetFade, &ClientGameCommandManager::SetFade },
|
|
|
|
{ &EV_Client_SetFadeDelay, &ClientGameCommandManager::SetFadeDelay },
|
|
|
|
{ &EV_Client_SetFadeIn, &ClientGameCommandManager::SetFadeIn },
|
|
|
|
{ &EV_Client_SetTwinkle, &ClientGameCommandManager::SetTwinkle },
|
|
|
|
{ &EV_Client_SetTrail, &ClientGameCommandManager::SetTrail },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_SetSpawnRange, &ClientGameCommandManager::SetSpawnRange },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetSpawnRate, &ClientGameCommandManager::SetSpawnRate },
|
|
|
|
{ &EV_Client_SetScaleRate, &ClientGameCommandManager::SetScaleRate },
|
|
|
|
{ &EV_Client_SetOriginOffset, &ClientGameCommandManager::SetOriginOffset },
|
|
|
|
{ &EV_Client_SetSphere, &ClientGameCommandManager::SetSphere },
|
|
|
|
{ &EV_Client_SetCircle, &ClientGameCommandManager::SetCircle },
|
|
|
|
{ &EV_Client_SetInwardSphere, &ClientGameCommandManager::SetInwardSphere },
|
|
|
|
{ &EV_Client_SetRadius, &ClientGameCommandManager::SetRadius },
|
|
|
|
{ &EV_Client_SetSwarm, &ClientGameCommandManager::SetSwarm },
|
|
|
|
{ &EV_Client_SetAlign, &ClientGameCommandManager::SetAlign },
|
|
|
|
{ &EV_Client_SetAlignOnce, &ClientGameCommandManager::SetAlignOnce },
|
|
|
|
{ &EV_Client_SetCollision, &ClientGameCommandManager::SetCollision },
|
|
|
|
{ &EV_Client_SetFlickerAlpha, &ClientGameCommandManager::SetFlickerAlpha },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_Sound, &ClientGameCommandManager::Sound },
|
|
|
|
{ &EV_Set_Current_Tiki, &ClientGameCommandManager::SetCurrentTiki },
|
|
|
|
{ &EV_Client_StopSound, &ClientGameCommandManager::StopSound },
|
|
|
|
{ &EV_Client_StopAliasChannel, &ClientGameCommandManager::StopAliasChannel },
|
|
|
|
{ &EV_Client_LoopSound, &ClientGameCommandManager::LoopSound },
|
|
|
|
{ &EV_Client_Cache, &ClientGameCommandManager::Cache },
|
|
|
|
{ &EV_Client_CacheImage, &ClientGameCommandManager::CacheImage },
|
|
|
|
{ &EV_Client_CacheFont, &ClientGameCommandManager::CacheFont },
|
|
|
|
{ &EV_Client_AliasCache, &ClientGameCommandManager::AliasCache },
|
|
|
|
{ &EV_Client_Alias, &ClientGameCommandManager::Alias },
|
|
|
|
{ &EV_Client_CacheAlias, &ClientGameCommandManager::CacheAlias },
|
|
|
|
{ &EV_Client_Footstep, &ClientGameCommandManager::Footstep },
|
|
|
|
{ &EV_Client_Landing, &ClientGameCommandManager::LandingSound },
|
|
|
|
{ &EV_Client_BodyFall, &ClientGameCommandManager::BodyFallSound },
|
|
|
|
{ &EV_Client_Client, &ClientGameCommandManager::Client },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_TagDynamicLight, &ClientGameCommandManager::TagDynamicLight },
|
|
|
|
{ &EV_Client_OriginDynamicLight, &ClientGameCommandManager::OriginDynamicLight },
|
|
|
|
{ &EV_Client_DynamicLight, &ClientGameCommandManager::DynamicLight },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_BlockDynamicLight, &ClientGameCommandManager::BlockDynamicLight },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetEntityColor, &ClientGameCommandManager::SetEntityColor },
|
|
|
|
{ &EV_Client_SetGlobalFade, &ClientGameCommandManager::SetGlobalFade },
|
|
|
|
{ &EV_Client_SetParentLink, &ClientGameCommandManager::SetParentLink },
|
|
|
|
{ &EV_Client_SetHardLink, &ClientGameCommandManager::SetHardLink },
|
|
|
|
{ &EV_Client_SetRandomRoll, &ClientGameCommandManager::SetRandomRoll },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_SetVolumetric, &ClientGameCommandManager::SetVolumetric },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetAngles, &ClientGameCommandManager::SetAngles },
|
|
|
|
{ &EV_Client_ParentAngles, &ClientGameCommandManager::ParentAngles },
|
|
|
|
{ &EV_Client_Swipe, &ClientGameCommandManager::Swipe },
|
|
|
|
{ &EV_Client_SwipeOn, &ClientGameCommandManager::SwipeOn },
|
|
|
|
{ &EV_Client_SwipeOff, &ClientGameCommandManager::SwipeOff },
|
|
|
|
{ &EV_Client_SetAnim, &ClientGameCommandManager::SetAnim },
|
|
|
|
{ &EV_Client_AnimateOnce, &ClientGameCommandManager::AnimateOnce },
|
|
|
|
{ &EV_Client_SetSubdivisions, &ClientGameCommandManager::SetSubdivisions },
|
|
|
|
{ &EV_Client_SetMinOffset, &ClientGameCommandManager::SetMinOffset },
|
|
|
|
{ &EV_Client_SetMaxOffset, &ClientGameCommandManager::SetMaxOffset },
|
|
|
|
{ &EV_Client_SetBeamShader, &ClientGameCommandManager::SetShader },
|
|
|
|
{ &EV_Client_SetBeamLength, &ClientGameCommandManager::SetLength },
|
|
|
|
{ &EV_Client_SetDecalShader, &ClientGameCommandManager::SetShader },
|
|
|
|
{ &EV_Client_SetTraceLength, &ClientGameCommandManager::SetLength },
|
|
|
|
{ &EV_Client_SetBeamDelay, &ClientGameCommandManager::SetBeamDelay },
|
|
|
|
{ &EV_Client_SetBeamToggleDelay, &ClientGameCommandManager::SetBeamToggleDelay },
|
|
|
|
{ &EV_Client_SetBeamPersist, &ClientGameCommandManager::SetBeamPersist },
|
|
|
|
{ &EV_Client_SetBeamOffsetEndpoints, &ClientGameCommandManager::SetBeamOffsetEndpoints },
|
|
|
|
{ &EV_Client_BeamSphere, &ClientGameCommandManager::SetBeamSphere },
|
|
|
|
{ &EV_Client_Spread, &ClientGameCommandManager::SetSpread },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_UseLastTraceEnd, &ClientGameCommandManager::SetUseLastTraceEnd },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_OffsetAlongAxis, &ClientGameCommandManager::SetOffsetAlongAxis },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_Cone, &ClientGameCommandManager::SetCone },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_SetEndAlpha, &ClientGameCommandManager::SetEndAlpha },
|
|
|
|
{ &EV_Client_RandomChance, &ClientGameCommandManager::RandomChance },
|
|
|
|
{ &EV_Client_CommandDelay, &ClientGameCommandManager::CommandDelay },
|
|
|
|
{ &EV_Client_BounceDecal, &ClientGameCommandManager::SetBounceDecal },
|
|
|
|
{ &EV_Client_SetDecalRadius, &ClientGameCommandManager::SetDecalRadius },
|
|
|
|
{ &EV_Client_SetDecalOrientation, &ClientGameCommandManager::SetDecalOrientation },
|
|
|
|
{ &EV_Client_TagList, &ClientGameCommandManager::TagList },
|
|
|
|
{ &EV_Client_Lightstyle, &ClientGameCommandManager::SetLightstyle },
|
|
|
|
{ &EV_Client_PhysicsRate, &ClientGameCommandManager::SetPhysicsRate },
|
|
|
|
{ &EV_Client_Parallel, &ClientGameCommandManager::SetParallel },
|
|
|
|
{ &EV_Client_Detail, &ClientGameCommandManager::SetDetail },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_Wind, &ClientGameCommandManager::SetWindAffect },
|
|
|
|
{ &EV_Client_SpriteGridLighting, &ClientGameCommandManager::SpriteGridLighting },
|
|
|
|
{ &EV_Client_WaterOnly, &ClientGameCommandManager::SetWaterOnly },
|
|
|
|
{ &EV_Client_SetAlignStretch, &ClientGameCommandManager::SetAlignStretch },
|
|
|
|
{ &EV_Client_SetClampVelocity, &ClientGameCommandManager::SetClampVel },
|
|
|
|
{ &EV_Client_SetClampVelocityAxis, &ClientGameCommandManager::SetClampVelAxis },
|
2023-04-30 01:42:57 +02:00
|
|
|
{ &EV_Client_Print, &ClientGameCommandManager::Print },
|
2023-05-05 23:43:27 +02:00
|
|
|
{ &EV_Client_EyeLimits, &ClientGameCommandManager::SetEyeLimits },
|
|
|
|
{ &EV_Client_EyeMovement, &ClientGameCommandManager::SetEyeMovement },
|
|
|
|
{ &EV_Client_SFXStart, &ClientGameCommandManager::StartSFX },
|
|
|
|
{ &EV_Client_SFXStartDelayed, &ClientGameCommandManager::StartSFXDelayed },
|
|
|
|
{ &EV_Client_Treads, &ClientGameCommandManager::SpawnTreads },
|
|
|
|
{ &EV_Client_Treads_Off, &ClientGameCommandManager::TreadsOff },
|
|
|
|
{ &EV_Client_ViewKick, &ClientGameCommandManager::EventViewKick },
|
2023-04-30 00:02:16 +02:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
static int DLightNameToNum(str s)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
if (!s.icmp("normal")) {
|
|
|
|
return 0;
|
|
|
|
} else if (!s.icmp("lensflare")) {
|
|
|
|
return lensflare;
|
|
|
|
} else if (!s.icmp("viewlensflare")) {
|
|
|
|
return viewlensflare;
|
|
|
|
} else if (!s.icmp("additive")) {
|
|
|
|
return additive;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
float RandomizeRange(float start, float end)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
float t;
|
|
|
|
|
|
|
|
if (start > end) {
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = start + ((end - start) * random());
|
|
|
|
return t;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-01 15:49:45 +02:00
|
|
|
void ClientGameCommandManager::ProcessPendingEventsForEntity()
|
|
|
|
{
|
2023-05-06 17:02:40 +02:00
|
|
|
EffectsEventQueueNode* event;
|
|
|
|
int t;
|
|
|
|
|
|
|
|
t = cg.time;
|
|
|
|
event = EffectsEventQueue.next;
|
|
|
|
while (event != &EffectsEventQueue && event->inttime <= t)
|
|
|
|
{
|
|
|
|
if (event->GetEntityNum() == current_entity_number)
|
|
|
|
{
|
|
|
|
// the event is removed from its list and temporarily added to the active list
|
|
|
|
LL_Remove(event, next, prev);
|
|
|
|
|
|
|
|
// ProcessEvent will dispose of this event when it is done
|
|
|
|
ProcessEvent(event->event);
|
|
|
|
|
|
|
|
// free up the node
|
|
|
|
delete event;
|
|
|
|
|
|
|
|
// start over, since can't guarantee that we didn't process any previous or following events
|
|
|
|
event = EffectsEventQueue.next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
}
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qboolean ClientGameCommandManager::PostEventForEntity(Event* ev, float fWait)
|
|
|
|
{
|
2023-05-06 17:02:40 +02:00
|
|
|
unsigned short evnum;
|
|
|
|
ClassDef* c;
|
|
|
|
EffectsEventQueueNode* event;
|
|
|
|
EffectsEventQueueNode* node;
|
|
|
|
int inttime;
|
|
|
|
|
|
|
|
if (!m_fEventWait || current_entity_number < 0)
|
|
|
|
{
|
|
|
|
if (!str::icmp(ev->getName(), ")")) {
|
|
|
|
m_fEventWait = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete ev;
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
evnum = ev->eventnum;
|
|
|
|
c = classinfo();
|
|
|
|
if (!c->responseLookup[evnum])
|
|
|
|
{
|
|
|
|
delete ev;
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = EffectsEventQueue.next;
|
|
|
|
inttime = EVENT_msec + (fWait * 1000.0f + 0.5f);
|
|
|
|
|
|
|
|
while (event != &EffectsEventQueue && inttime > event->inttime)
|
|
|
|
{
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_fEventWait != 0.0)
|
|
|
|
{
|
|
|
|
if (!str::icmp(ev->getName(), ")")) {
|
|
|
|
m_fEventWait = 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
node = new EffectsEventQueueNode(ev, inttime, 0, current_entity_number);
|
|
|
|
LL_Add(event, node, next, prev);
|
|
|
|
|
|
|
|
return qtrue;
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBaseAndAmplitude(Event* ev, Vector& base, Vector& amplitude)
|
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
while (j < 3) {
|
|
|
|
str org;
|
|
|
|
|
|
|
|
org = ev->GetString(i++);
|
|
|
|
if (org == "crandom") {
|
|
|
|
float value = ev->GetFloat(i++);
|
|
|
|
base[j] = -value;
|
|
|
|
amplitude[j] = value + value;
|
|
|
|
} else if (org == "random") {
|
|
|
|
base[j] = 0.0;
|
|
|
|
amplitude[j] = ev->GetFloat(i++);
|
|
|
|
} else if (org == "range") {
|
|
|
|
base[j] = ev->GetFloat(i++);
|
|
|
|
amplitude[j] = ev->GetFloat(i++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// ClientGameCommandManager
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
ClientGameCommandManager::ClientGameCommandManager()
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_seed = 0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
InitializeTempModels();
|
|
|
|
InitializeEmitters();
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::Print(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
if (current_entity) {
|
|
|
|
cgi.DPrintf("%d:%s\n", current_entity->entityNumber, ev->GetString(1));
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
qboolean ClientGameCommandManager::IsBlockCommand(const str& name)
|
|
|
|
{
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::DelayedRepeat(Event* ev)
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
2023-05-06 23:37:05 +02:00
|
|
|
float delay;
|
2023-04-30 20:20:58 +02:00
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
delay = ev->GetFloat(1) * 1000.0;
|
|
|
|
if (current_entity)
|
|
|
|
{
|
2023-04-30 20:20:58 +02:00
|
|
|
commandtime_t* ct = m_command_time_manager.GetLastCommandTime(
|
|
|
|
current_entity->entityNumber, ev->GetInteger(2));
|
|
|
|
|
|
|
|
if (!ct->last_command_time) {
|
|
|
|
ct->last_command_time = cg.time + delay;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ct->last_command_time > cg.time) {
|
|
|
|
return;
|
2023-05-06 23:37:05 +02:00
|
|
|
}
|
|
|
|
else {
|
2023-04-30 20:20:58 +02:00
|
|
|
ct->last_command_time = cg.time + delay;
|
|
|
|
}
|
|
|
|
}
|
2023-05-06 23:37:05 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Class::warning("CCM:DelayedRepeat", "Cannot perform delayed repeat on spawned tempmodels");
|
|
|
|
|
|
|
|
Event ev1(ev->GetString(3));
|
2023-04-30 20:20:58 +02:00
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
for (i = 4; i <= ev->NumArgs(); i++)
|
|
|
|
{
|
|
|
|
ev1.AddToken(ev->GetToken(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcessEvent(ev1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Event ev1(ev->GetString(3));
|
2023-04-30 20:20:58 +02:00
|
|
|
|
|
|
|
for (i = 4; i <= ev->NumArgs(); i++) {
|
2023-05-06 23:37:05 +02:00
|
|
|
ev1.AddToken(ev->GetToken(i));
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
ProcessEvent(ev1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
//===============
|
|
|
|
// CommandDelay
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::CommandDelay(Event* ev)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int num;
|
|
|
|
float fWait;
|
|
|
|
str eventName;
|
|
|
|
int delay;
|
|
|
|
Event* ev1;
|
|
|
|
|
|
|
|
fWait = ev->GetFloat(1);
|
|
|
|
eventName = ev->GetString(2);
|
|
|
|
|
|
|
|
ev1 = new Event(eventName);
|
|
|
|
|
|
|
|
num = ev->NumArgs();
|
|
|
|
for (i = 3; i <= num; i++) {
|
|
|
|
ev1->AddValue(ev->GetValue(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
delay = ev->GetFloat(1) * 1000;
|
|
|
|
if (current_entity_number != -1) {
|
|
|
|
PostEventForEntity(ev1, fWait);
|
|
|
|
} else {
|
|
|
|
warning("CCM:CommandDelay",
|
|
|
|
"Can't use commanddelay in temp models. Found illegal commanddelay in '%s'\n",
|
|
|
|
current_tiki->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::StartSFX(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
StartSFXCommand(ev, qfalse);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::StartSFXDelayed(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
StartSFXCommand(ev, qtrue);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-05-06 20:54:14 +02:00
|
|
|
void ClientGameCommandManager::StartSFXCommand(Event* ev, qboolean bDelayed)
|
2023-05-05 22:58:34 +02:00
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
qboolean bBlockCommand;
|
|
|
|
int i;
|
|
|
|
int iArgOfs;
|
|
|
|
float delay;
|
|
|
|
str sCommandName;
|
|
|
|
specialeffectcommand_t* pCommand;
|
|
|
|
|
|
|
|
if (bDelayed)
|
|
|
|
{
|
|
|
|
delay = ev->GetFloat(1);
|
|
|
|
iArgOfs = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delay = 0.0;
|
|
|
|
iArgOfs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sCommandName = ev->GetString(iArgOfs + 1);
|
|
|
|
bBlockCommand = IsBlockCommand(sCommandName);
|
|
|
|
if (!m_pCurrentSfx)
|
|
|
|
{
|
|
|
|
if (bBlockCommand)
|
|
|
|
{
|
|
|
|
m_spawnthing = &m_localemitter;
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndIgnoreSfxBlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!current_entity) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCommand = m_pCurrentSfx->AddNewCommand();
|
|
|
|
if (!pCommand) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bBlockCommand)
|
|
|
|
{
|
|
|
|
m_spawnthing = new spawnthing_t;
|
|
|
|
pCommand->emitter = m_spawnthing;
|
|
|
|
}
|
|
|
|
pCommand->fCommandTime = delay;
|
|
|
|
|
|
|
|
Event* ev1 = new Event(sCommandName);
|
|
|
|
for (i = iArgOfs + 2; i <= ev->NumArgs(); i++) {
|
|
|
|
ev1->AddToken(ev->GetToken(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bBlockCommand) {
|
|
|
|
ProcessEvent(ev1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pCommand->pEvent = ev1;
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::EndIgnoreSfxBlock()
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
endblockfcn = NULL;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-05-05 21:11:48 +02:00
|
|
|
void ClientGameCommandManager::SetCurrentSFX(specialeffect_t* pSFX)
|
2023-05-01 15:49:45 +02:00
|
|
|
{
|
2023-05-05 21:11:48 +02:00
|
|
|
m_pCurrentSfx = pSFX;
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::ClearCurrentSFX()
|
|
|
|
{
|
2023-05-05 21:11:48 +02:00
|
|
|
m_pCurrentSfx = NULL;
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// RandomChance
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::RandomChance(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float percentage = ev->GetFloat(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if ((random() < percentage) && (ev->NumArgs() >= 2)) {
|
|
|
|
Event* ev1;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
ev1 = new Event(ev->GetString(2));
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 3; i <= ev->NumArgs(); i++) {
|
|
|
|
ev1->AddToken(ev->GetToken(i));
|
|
|
|
}
|
|
|
|
ProcessEvent(ev1);
|
|
|
|
}
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
|
2023-05-06 20:54:14 +02:00
|
|
|
void ClientGameCommandManager::SetAlwaysDraw(Event* ev)
|
|
|
|
{
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_ALWAYSDRAW;
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// SetDetail
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetDetail(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_DETAIL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetWindAffect(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_WIND_AFFECT;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SpriteGridLighting(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_SPRITEGRIDLIGHTING;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetWaterOnly(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_WATERONLY;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetClampVel(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() != 6) {
|
|
|
|
cgi.Printf("clampvel has 6 arguments\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_CLAMP_VEL;
|
|
|
|
// cannot be both clamp vel and clamp vel axis
|
|
|
|
m_spawnthing->cgd.flags2 &= ~T2_CLAMP_VEL_AXIS;
|
|
|
|
|
|
|
|
m_spawnthing->cgd.minVel[0] = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.maxVel[0] = ev->GetFloat(2);
|
|
|
|
m_spawnthing->cgd.minVel[1] = ev->GetFloat(3);
|
|
|
|
m_spawnthing->cgd.maxVel[1] = ev->GetFloat(4);
|
|
|
|
m_spawnthing->cgd.minVel[2] = ev->GetFloat(5);
|
|
|
|
m_spawnthing->cgd.maxVel[2] = ev->GetFloat(6);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetClampVelAxis(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() != 6) {
|
|
|
|
cgi.Printf("clampvel has 6 arguments\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_CLAMP_VEL_AXIS;
|
|
|
|
// cannot be both clamp vel and clamp vel axis
|
|
|
|
m_spawnthing->cgd.flags2 &= ~T2_CLAMP_VEL;
|
|
|
|
|
|
|
|
m_spawnthing->cgd.minVel[0] = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.maxVel[0] = ev->GetFloat(2);
|
|
|
|
m_spawnthing->cgd.minVel[1] = ev->GetFloat(3);
|
|
|
|
m_spawnthing->cgd.maxVel[1] = ev->GetFloat(4);
|
|
|
|
m_spawnthing->cgd.minVel[2] = ev->GetFloat(5);
|
|
|
|
m_spawnthing->cgd.maxVel[2] = ev->GetFloat(6);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetAlignStretch(Event* ev)
|
|
|
|
{
|
2023-05-06 20:54:14 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags |= T_ALIGN;
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_ALIGNSTRETCH;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
m_spawnthing->cgd.scale2 = ev->GetFloat(1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_spawnthing->cgd.scale2 = 1.0;
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// SetDecalRadius
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetDecalRadius(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.decal_radius = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetDecalOrientation
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetDecalOrientation(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str deg;
|
|
|
|
|
|
|
|
deg = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!deg.icmp("random")) {
|
|
|
|
m_spawnthing->cgd.decal_orientation = random() * 360;
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.decal_orientation = ev->GetFloat(1);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBounceDecal
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBounceDecal(Event* ev)
|
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_BOUNCE_DECAL;
|
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
m_spawnthing->cgd.maxbouncecount = ev->GetInteger(1);
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
qboolean b = ev->GetBoolean(2);
|
|
|
|
if (b) {
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_TEMPORARY_DECAL;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetParallel
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetParallel(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_PARALLEL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// PhysicsRate
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetPhysicsRate(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str rate;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
rate = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!rate.icmp(rate, "every")) {
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_PHYSICS_EVERYFRAME;
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.physicsRate = atof(rate);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetLightstyle
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetLightstyle(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.lightstyle = CG_RegisterLightStyle(ev->GetString(1));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamSphere
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBeamSphere(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->numspherebeams = ev->GetInteger(1);
|
|
|
|
m_spawnthing->beamflags = BEAM_SPHERE_EFFECT;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamSpread
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetSpread(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->spreadx = ev->GetFloat(1);
|
|
|
|
m_spawnthing->spready = ev->GetFloat(2);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetUseLastTraceEnd
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetUseLastTraceEnd(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->use_last_trace_end = qtrue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetSubdivisions
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetSubdivisions(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->numSubdivisions = ev->GetInteger(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamPersist
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBeamPersist(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->beamflags |= BEAM_PERSIST_EFFECT;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamOffsetEndponts
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBeamOffsetEndpoints(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->beamflags |= BEAM_OFFSET_ENDPOINTS;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamDelay
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBeamDelay(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
str r = ev->GetString(1);
|
|
|
|
if (r.icmp("random")) {
|
|
|
|
m_spawnthing->beamflags |= BEAM_RANDOM_DELAY;
|
|
|
|
}
|
|
|
|
m_spawnthing->delay = ev->GetFloat(2) * 1000.0f;
|
|
|
|
} else {
|
|
|
|
m_spawnthing->delay = ev->GetFloat(1) * 1000.0f;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamToggleDelay
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBeamToggleDelay(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->beamflags |= BEAM_TOGGLE;
|
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
str r = ev->GetString(1);
|
|
|
|
if (!r.icmp("random")) {
|
|
|
|
m_spawnthing->beamflags |= BEAM_RANDOM_TOGGLEDELAY;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->toggledelay = ev->GetFloat(2) * 1000.0f;
|
|
|
|
} else {
|
|
|
|
m_spawnthing->toggledelay = ev->GetFloat(1) * 1000.0f;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetBeamLength
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetLength(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->length = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetShader
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetShader(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.shadername = ev->GetString(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetMinOffset
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetMinOffset(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->min_offset = ev->GetInteger(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetSubdivisions
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetMaxOffset(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->max_offset = ev->GetInteger(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// SetAnim
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAnim(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->animName = ev->GetString(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// AnimateOnce
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::AnimateOnce(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_ANIMATEONCE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EmitterStartOff
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EmitterStartOff(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->startoff = qtrue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// StartBlock
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::StartBlock(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Make sure there are no more args on this line, because
|
|
|
|
// they will be lost
|
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
cgi.DPrintf("CCM::StartBlock : Invalid commands on start block '{'\n");
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndBlock
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndBlock(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Make sure there are no more args on this line, because
|
|
|
|
// they will be lost
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
cgi.DPrintf("CCM::StartBlock : Invalid commands on start block '{'\n");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (endblockfcn) {
|
|
|
|
(this->*endblockfcn)();
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
endblockfcn = NULL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetSwarm
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetSwarm(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.swarmfreq = ev->GetInteger(1);
|
|
|
|
m_spawnthing->cgd.swarmmaxspeed = ev->GetFloat(2);
|
|
|
|
m_spawnthing->cgd.swarmdelta = ev->GetFloat(3);
|
|
|
|
m_spawnthing->cgd.flags |= T_SWARM;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetCircle
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetCircle(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_CIRCLE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetSphere
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetSphere(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_SPHERE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetSphere
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetRadius(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->sphereRadius = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetInwardSphere
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetInwardSphere(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_INWARDSPHERE;
|
|
|
|
m_spawnthing->sphereRadius = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAlign
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAlign(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_ALIGN;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAlignOnce
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAlignOnce(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_ALIGNONCE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetRandomRoll
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetRandomRoll(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_RANDOMROLL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetVolumetric(Event* ev)
|
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_VOLUMETRIC;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetCollision
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetCollision(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str mask;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_COLLISION;
|
|
|
|
m_spawnthing->cgd.collisionmask = (CONTENTS_SOLID);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
mask = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (mask == "water") {
|
|
|
|
m_spawnthing->cgd.collisionmask = (CONTENTS_SOLID | CONTENTS_WATER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetFlickerAlpha
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetFlickerAlpha(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_FLICKERALPHA;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetEndAlpha
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetEndAlpha(Event* ev)
|
|
|
|
{
|
|
|
|
m_spawnthing->endalpha = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetOffsetAlongAxis
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetOffsetAlongAxis(Event* ev)
|
|
|
|
{
|
|
|
|
if (m_spawnthing) {
|
|
|
|
SetBaseAndAmplitude(ev, m_spawnthing->axis_offset_base, m_spawnthing->axis_offset_amplitude);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetCone(Event* ev)
|
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_CONE;
|
|
|
|
m_spawnthing->coneHeight = ev->GetFloat(1);
|
|
|
|
m_spawnthing->sphereRadius = ev->GetFloat(2);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//=============
|
|
|
|
// SetOriginOffset
|
|
|
|
//=============
|
|
|
|
void ClientGameCommandManager::SetOriginOffset(Event* ev)
|
|
|
|
{
|
|
|
|
if (m_spawnthing) {
|
|
|
|
SetBaseAndAmplitude(ev, m_spawnthing->origin_offset_base,
|
|
|
|
m_spawnthing->origin_offset_amplitude);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAlpha
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAlpha(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.alpha = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetDieTouch
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetDieTouch(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_DIETOUCH;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetBounceFactor
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBounceFactor(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.bouncefactor = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.flags |= T_COLLISION;
|
|
|
|
m_spawnthing->cgd.collisionmask = (CONTENTS_SOLID);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetBounceSound
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBounceSound(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.bouncesound = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
m_spawnthing->cgd.bouncesound_delay = ev->GetFloat(1) * 1000;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags |= T_BOUNCESOUND;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetBounceSoundOnce
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetBounceSoundOnce(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_BOUNCESOUNDONCE;
|
|
|
|
SetBounceSound(ev);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetScale
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetScale(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.scale = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetScaleUpDown
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetScaleUpDown(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_SCALEUPDOWN;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetScaleMin
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetScaleMin(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_RANDSCALE;
|
|
|
|
m_spawnthing->cgd.scalemin = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetScaleMax
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetScaleMax(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_RANDSCALE;
|
|
|
|
m_spawnthing->cgd.scalemax = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetScaleRate
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetScaleRate(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.scaleRate = ev->GetFloat(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetFade
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetFade(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_FADE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetFadeDelay
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetFadeDelay(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.fadedelay = ev->GetFloat(1) * 1000;
|
|
|
|
m_spawnthing->cgd.flags |= T_FADE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetSpawnRange(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
float fVal1, fVal2;
|
|
|
|
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 1)
|
|
|
|
{
|
|
|
|
cgi.DPrintf("too few arguments to spawnrange");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fVal1 = ev->GetFloat(1);
|
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
fVal2 = ev->GetFloat(2);
|
|
|
|
}
|
2023-05-07 14:45:23 +02:00
|
|
|
else {
|
|
|
|
fVal2 = 0.0;
|
|
|
|
}
|
2023-05-06 23:37:05 +02:00
|
|
|
|
|
|
|
if (fVal1 * fVal1 > fVal2 * fVal2)
|
|
|
|
{
|
|
|
|
m_spawnthing->fMinRangeSquared = fVal2 * fVal2;
|
|
|
|
m_spawnthing->fMaxRangeSquared = fVal1 * fVal1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_spawnthing->fMinRangeSquared = fVal1 * fVal1;
|
|
|
|
m_spawnthing->fMaxRangeSquared = fVal2 * fVal2;
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetFadeIn
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetFadeIn(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_FADEIN;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
m_spawnthing->cgd.fadeintime = ev->GetFloat(1) * 1000;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetTwinkle
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetTwinkle(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_TWINKLE;
|
|
|
|
m_spawnthing->cgd.min_twinkletimeoff = ev->GetFloat(1) * 1000;
|
|
|
|
m_spawnthing->cgd.max_twinkletimeoff = ev->GetFloat(2) * 1000;
|
|
|
|
m_spawnthing->cgd.min_twinkletimeon = ev->GetFloat(3) * 1000;
|
|
|
|
m_spawnthing->cgd.max_twinkletimeon = ev->GetFloat(4) * 1000;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetSwipe
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetTrail(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_TRAIL;
|
|
|
|
m_spawnthing->cgd.swipe_shader = ev->GetString(1);
|
|
|
|
m_spawnthing->cgd.swipe_tag_start = ev->GetString(2);
|
|
|
|
m_spawnthing->cgd.swipe_tag_end = ev->GetString(3);
|
|
|
|
m_spawnthing->cgd.swipe_life = ev->GetFloat(4);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetSpawnRate
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetSpawnRate(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->spawnRate = (1.0f / ev->GetFloat(1)) * 1000;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetParentLink
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetParentLink(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_PARENTLINK;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetHardLink
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetHardLink(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_HARDLINK;
|
|
|
|
m_spawnthing->cgd.parent = current_entity_number;
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
m_spawnthing->cgd.origin =
|
|
|
|
m_spawnthing->cgd.origin - current_entity->origin;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetColor
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetColor(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.color[0] = ev->GetFloat(1) * 0xff;
|
|
|
|
m_spawnthing->cgd.color[1] = ev->GetFloat(2) * 0xff;
|
|
|
|
m_spawnthing->cgd.color[2] = ev->GetFloat(3) * 0xff;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() == 4) {
|
|
|
|
m_spawnthing->cgd.color[3] = ev->GetFloat(4) * 0xff;
|
|
|
|
m_spawnthing->cgd.alpha = ev->GetFloat(4);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetColorRange(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// FIXME: unused stub??
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetEntityColor
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetEntityColor(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
if (current_centity) {
|
|
|
|
current_centity->client_color[0] = ev->GetFloat(1);
|
|
|
|
current_centity->client_color[1] = ev->GetFloat(2);
|
|
|
|
current_centity->client_color[2] = ev->GetFloat(3);
|
|
|
|
if (ev->NumArgs() == 4) {
|
|
|
|
current_centity->client_color[3] = ev->GetFloat(4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetGlobalFade
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetGlobalFade(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str mode;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
mode = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (mode == "in") {
|
|
|
|
m_spawnthing->cgd.flags |= T_GLOBALFADEIN;
|
|
|
|
} else if (mode == "out") {
|
|
|
|
m_spawnthing->cgd.flags |= T_GLOBALFADEOUT;
|
|
|
|
} else {
|
|
|
|
cgi.DPrintf("Illegal globalfade parm: %s\n", mode.c_str());
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetRandomVelocity
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetRandomVelocity(Event* ev)
|
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
int j = 0;
|
|
|
|
Vector randval;
|
|
|
|
str vel;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() < 3) {
|
|
|
|
warning("ClientGameCommandManager::SetRandomVelocity",
|
|
|
|
"Expecting at least 3 args for command randvel");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
SetBaseAndAmplitude(ev, m_spawnthing->randvel_base,
|
|
|
|
m_spawnthing->randvel_amplitude);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.flags2 |= T2_MOVE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetRandomVelocityAlongAxis
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetRandomVelocityAlongAxis(Event* ev)
|
|
|
|
{
|
|
|
|
m_spawnthing->cgd.flags |= T_RANDVELAXIS;
|
|
|
|
SetRandomVelocity(ev);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetRadialVelocity(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 3) {
|
|
|
|
warning("ClientGameCommandManager::SetRadialVelocity", "Missing parameters for command radialvelocity");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.velocity[0] = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.velocity[1] = ev->GetFloat(2);
|
|
|
|
m_spawnthing->cgd.velocity[2] = ev->GetFloat(3);
|
|
|
|
m_spawnthing->cgd.velocity[2] -= m_spawnthing->cgd.velocity[1];
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_RADIALVELOCITY | T2_MOVE;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetVelocity
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetVelocity(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->forwardVelocity = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_MOVE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAngularVelocity
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAngularVelocity(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
int j = 0;
|
|
|
|
Vector randval;
|
|
|
|
str vel;
|
|
|
|
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 3) {
|
|
|
|
warning("ClientGameCommandManager::SetAngularVelocity",
|
|
|
|
"Expecting at least 3 args for command randvel");
|
|
|
|
}
|
|
|
|
|
|
|
|
SetBaseAndAmplitude(ev, m_spawnthing->avelocity_base,
|
|
|
|
m_spawnthing->avelocity_amplitude);
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_AMOVE;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAngles
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAngles(Event* ev)
|
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
int j = 0;
|
|
|
|
Vector randval;
|
|
|
|
str vel;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 3) {
|
|
|
|
warning("ClientGameCommandManager::SetAngles",
|
|
|
|
"Expecting at least 3 args for command randvel");
|
|
|
|
}
|
|
|
|
|
|
|
|
SetBaseAndAmplitude(ev, m_spawnthing->cgd.angles,
|
|
|
|
m_spawnthing->angles_amplitude);
|
|
|
|
|
|
|
|
// Set the tag axis
|
|
|
|
m_spawnthing->cgd.flags |= T_ANGLES;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// ParentAngles
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::ParentAngles(Event* ev)
|
|
|
|
{
|
|
|
|
if (current_centity) {
|
|
|
|
m_spawnthing->cgd.angles = Vector(current_centity->currentState.angles);
|
|
|
|
}
|
|
|
|
m_spawnthing->cgd.flags |= T_ANGLES;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::EmitterAngles(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixToEulerAngles(m_spawnthing->tag_axis, m_spawnthing->cgd.angles);
|
|
|
|
if (ev->NumArgs() > 0) m_spawnthing->cgd.angles[0] = ev->GetFloat(1);
|
|
|
|
if (ev->NumArgs() > 1) m_spawnthing->cgd.angles[1] = ev->GetFloat(2);
|
|
|
|
if (ev->NumArgs() > 2) m_spawnthing->cgd.angles[2] = ev->GetFloat(3);
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags |= T_ANGLES;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetAccel
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetAccel(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
m_spawnthing->cgd.accel[0] = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.accel[1] = ev->GetFloat(2);
|
|
|
|
m_spawnthing->cgd.accel[2] = ev->GetFloat(3);
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_ACCEL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetFriction(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.friction = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_FRICTION;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetVaryColor(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags2 |= T2_VARYCOLOR;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetCount
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetCount(Event* ev)
|
|
|
|
{
|
|
|
|
m_spawnthing->count = ev->GetInteger(1);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetLife
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetLife(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str life;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
life = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!life.icmp("autocalc")) {
|
|
|
|
m_spawnthing->cgd.flags |= T_AUTOCALCLIFE;
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.life = atof(life) * 1000;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// SetModel
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SetModel(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int num = ev->NumArgs();
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 1; i <= num; i++) {
|
|
|
|
str s_arg(ev->GetString(i));
|
|
|
|
m_spawnthing->m_modellist.AddObject(s_arg);
|
|
|
|
CacheResource(ev->GetString(i));
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// TagList
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::TagList(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int num = ev->NumArgs();
|
|
|
|
|
|
|
|
if (num < 2) {
|
|
|
|
warning("CCG::TagList", "Invalid number of tags specified in taglist. "
|
|
|
|
"Minimum set of tags is 2.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 1; i <= num; i++) {
|
|
|
|
str s_arg(ev->GetString(i));
|
|
|
|
m_spawnthing->m_taglist.AddObject(s_arg);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SetEyeLimits(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (ev->NumArgs() < 3)
|
|
|
|
{
|
|
|
|
warning("CCG::SetEyeLimits", "Invalid number of parameters.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cg.vEyeOffsetMax[0] = ev->GetFloat(1);
|
|
|
|
cg.vEyeOffsetMax[2] = ev->GetFloat(2);
|
|
|
|
cg.fEyeOffsetFrac = ev->GetFloat(3);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetEyeMovement(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (ev->NumArgs() < 1)
|
|
|
|
{
|
|
|
|
warning("CCG::SetEyeMovement", "No parameters specified.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cg.fEyeOffsetFrac = ev->GetFloat(1);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// InitializeSpawnthing
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
spawnthing_t* ClientGameCommandManager::InitializeSpawnthing(spawnthing_t* sp)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// Initalize m_spawnthing - these can be overidden with other commands
|
|
|
|
sp->m_modellist.ClearObjectList();
|
|
|
|
AxisClear(sp->axis);
|
|
|
|
AxisClear(sp->tag_axis);
|
|
|
|
|
|
|
|
sp->startoff = qfalse;
|
|
|
|
sp->origin_offset_base = Vector(0, 0, 0);
|
|
|
|
sp->origin_offset_amplitude = Vector(0, 0, 0);
|
|
|
|
sp->axis_offset_base = Vector(0, 0, 0);
|
|
|
|
sp->axis_offset_amplitude = Vector(0, 0, 0);
|
|
|
|
sp->randvel_base = Vector(0, 0, 0);
|
|
|
|
sp->randvel_amplitude = Vector(0, 0, 0);
|
|
|
|
sp->avelocity_base = Vector(0, 0, 0);
|
|
|
|
sp->avelocity_amplitude = Vector(0, 0, 0);
|
|
|
|
sp->angles_amplitude = Vector(0, 0, 0);
|
|
|
|
sp->life_random = 0;
|
|
|
|
sp->forwardVelocity = 0;
|
|
|
|
sp->sphereRadius = 0;
|
|
|
|
sp->coneHeight = 0;
|
|
|
|
sp->spawnRate = 0.1f;
|
|
|
|
sp->count = 1;
|
|
|
|
sp->length = 1000;
|
|
|
|
sp->max_offset = 0;
|
|
|
|
sp->min_offset = 0;
|
|
|
|
sp->overlap = 0;
|
|
|
|
sp->numSubdivisions = 1;
|
|
|
|
sp->delay = 0;
|
|
|
|
sp->toggledelay = 0;
|
|
|
|
sp->endalpha = 1.0f;
|
|
|
|
sp->spreadx = 0;
|
|
|
|
sp->spready = 0;
|
|
|
|
sp->beamflags = 0;
|
|
|
|
sp->startoff = 0;
|
|
|
|
sp->numspherebeams = 0;
|
|
|
|
sp->use_last_trace_end = qfalse;
|
|
|
|
sp->tagnum = -1;
|
|
|
|
sp->numtempmodels = 0;
|
|
|
|
sp->entnum = ENTITYNUM_NONE;
|
|
|
|
|
|
|
|
sp->cgd.scale = 1.0f;
|
|
|
|
sp->cgd.createTime = cg.time;
|
|
|
|
sp->cgd.life = EMITTER_DEFAULT_LIFE;
|
|
|
|
sp->cgd.avelocity = Vector(0, 0, 0);
|
|
|
|
sp->cgd.accel = Vector(0, 0, 0);
|
|
|
|
sp->cgd.origin = Vector(0, 0, 0);
|
|
|
|
sp->cgd.oldorigin = Vector(0, 0, 0);
|
|
|
|
sp->cgd.angles = Vector(0, 0, 0);
|
|
|
|
sp->cgd.alpha = 1.0f;
|
|
|
|
sp->cgd.scalemin = 0;
|
|
|
|
sp->cgd.scalemax = 999999.0f;
|
|
|
|
sp->cgd.scaleRate = 0;
|
|
|
|
sp->cgd.bouncefactor = 0.3f;
|
|
|
|
sp->cgd.bouncesound = "";
|
|
|
|
sp->cgd.bouncesound_delay = 1000;
|
|
|
|
sp->cgd.bouncecount = 0;
|
|
|
|
sp->cgd.maxbouncecount = 3;
|
|
|
|
sp->cgd.flags = 0;
|
|
|
|
sp->cgd.flags2 = 0;
|
|
|
|
sp->cgd.swarmfreq = 0;
|
|
|
|
sp->cgd.swarmdelta = 0;
|
|
|
|
sp->cgd.swarmmaxspeed = 0;
|
|
|
|
sp->cgd.fadeintime = 0;
|
|
|
|
sp->cgd.fadedelay = 0;
|
|
|
|
sp->cgd.lightIntensity = 0;
|
|
|
|
sp->cgd.lightType = 0;
|
|
|
|
sp->cgd.collisionmask = MASK_AUTOCALCLIFE;
|
|
|
|
sp->cgd.parent = -1;
|
|
|
|
sp->cgd.tiki = nullptr;
|
|
|
|
sp->cgd.lightstyle = -1;
|
|
|
|
sp->cgd.physicsRate = 10;
|
|
|
|
sp->cgd.shadername = "beamshader";
|
|
|
|
sp->cgd.decal_orientation = 0;
|
|
|
|
sp->cgd.decal_radius = 10;
|
|
|
|
sp->cgd.max_twinkletimeoff = 0;
|
|
|
|
sp->cgd.min_twinkletimeoff = 0;
|
|
|
|
sp->cgd.max_twinkletimeon = 0;
|
|
|
|
sp->cgd.min_twinkletimeon = 0;
|
|
|
|
sp->cgd.swipe_life = 0;
|
|
|
|
sp->fMinRangeSquared = 0;
|
|
|
|
sp->fMaxRangeSquared = 9.9999997e37f;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
sp->dcolor[i] = 1.0f;
|
|
|
|
sp->cgd.color[i] = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->cgd.color[3] = 1.0;
|
|
|
|
|
|
|
|
return sp;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::SpawnEffect(int count, spawnthing_t* sp)
|
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
m_spawnthing = sp;
|
|
|
|
if (m_spawnthing->cgd.flags2 & T2_VOLUMETRIC)
|
|
|
|
{
|
|
|
|
// volumetric smoke
|
|
|
|
SpawnVSSSource(count, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SpawnTempModel(count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SpawnEffect(int count, int timealive)
|
|
|
|
{
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_spawnthing->cgd.flags2 & T2_VOLUMETRIC)
|
|
|
|
{
|
|
|
|
// volumetric smoke
|
|
|
|
SpawnVSSSource(count, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SpawnTempModel(count);
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
// GetEmitterByName
|
2023-04-30 00:02:16 +02:00
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
spawnthing_t* ClientGameCommandManager::GetEmitterByName(str name)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
spawnthing_t* st = m_emitters.ObjectAt(i);
|
|
|
|
if (st->emittername == name) {
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CreateNewEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
spawnthing_t* ClientGameCommandManager::CreateNewEmitter(str name)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
spawnthing_t* st;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
st = new spawnthing_t;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the emitter and set the internal pointer at it
|
|
|
|
InitializeSpawnthing(st);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Set the emitter's name
|
|
|
|
st->emittername = name;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Store it in the container
|
|
|
|
m_emitters.AddObject(st);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
return st;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-01 15:11:08 +02:00
|
|
|
void ClientGameCommandManager::DeleteEmitters(dtiki_t* tiki)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int i;
|
|
|
|
spawnthing_t* spawnthing;
|
|
|
|
|
|
|
|
for (i = m_emitters.NumObjects(); i > 0; i--)
|
|
|
|
{
|
|
|
|
spawnthing = m_emitters.ObjectAt(i);
|
|
|
|
if (spawnthing->cgd.tiki == tiki)
|
|
|
|
{
|
|
|
|
m_emitters.RemoveObjectAt(i);
|
|
|
|
delete spawnthing;
|
|
|
|
}
|
|
|
|
}
|
2023-05-01 15:11:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CG_DeleteEmitters(dtiki_t* tiki)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
commandManager.DeleteEmitters(tiki);
|
2023-05-01 15:11:08 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CreateNewEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//==================
|
2023-04-30 20:20:58 +02:00
|
|
|
spawnthing_t* ClientGameCommandManager::CreateNewEmitter(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
return CreateNewEmitter("");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginOriginSpawn
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginOriginSpawn(Event* ev)
|
|
|
|
{
|
|
|
|
// FIXME: partially implemented
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!current_entity) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndOriginSpawn;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the thing we are going to spawn
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Set the origin based on the entity's origin
|
|
|
|
m_spawnthing->cgd.origin = current_entity->origin;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Set the axis based on the entity's axis
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->axis);
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->tag_axis);
|
|
|
|
MatrixToEulerAngles(m_spawnthing->axis, m_spawnthing->cgd.angles);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndOriginSpawn
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndOriginSpawn(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Okay we should have a valid spawnthing, let's create a render entity
|
|
|
|
SpawnTempModel(m_spawnthing->count);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-01 15:49:45 +02:00
|
|
|
void ClientGameCommandManager::TestEffectEndFunc()
|
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpawnEffect(m_spawnthing->count, 0);
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// UpdateSpawnThing
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::UpdateSpawnThing(spawnthing_t* ep)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
orientation_t orientation;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
VectorCopy(current_entity->origin, ep->cgd.origin);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
VectorMA(ep->cgd.origin, orientation.origin[i], current_entity->axis[i],
|
|
|
|
ep->cgd.origin);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
MatrixMultiply(orientation.axis, current_entity->axis, ep->axis);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginTagEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginTagEmitter(Event* ev)
|
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
int tagnum;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the tagname and orientation
|
|
|
|
tagname = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!tagname.length()) {
|
|
|
|
warning("CCM::BeginTagEmitter",
|
|
|
|
"Tagname not specified for tagemitter in model: '%s'\n",
|
|
|
|
cgi.TIKI_Name(current_tiki));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist", tagname.c_str());
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndTagEmitter;
|
|
|
|
|
|
|
|
// Init the emitter
|
|
|
|
m_spawnthing = CreateNewEmitter();
|
|
|
|
m_spawnthing->tagnum = tagnum;
|
|
|
|
m_spawnthing->emittername = ev->GetString(2);
|
|
|
|
if (!m_spawnthing->emittername.length()) {
|
|
|
|
warning("CCM::BeginTagEmitter",
|
|
|
|
"Emittername not specified for tagemitter in model: '%s'\n",
|
|
|
|
cgi.TIKI_Name(current_tiki));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.tiki = current_tiki;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndTagEmitter
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndTagEmitter(void) { endblockfcn = NULL; }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginTagBeamEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginTagBeamEmitter(Event* ev)
|
|
|
|
|
|
|
|
{
|
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndTagBeamEmitter;
|
|
|
|
|
|
|
|
// Init the emitter
|
|
|
|
m_spawnthing = CreateNewEmitter();
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags |= T_BEAMTHING;
|
|
|
|
|
|
|
|
// Get the tagname and orientation
|
|
|
|
|
|
|
|
m_spawnthing->startTag = ev->GetString(1);
|
|
|
|
|
|
|
|
if (m_spawnthing->startTag == "USE_TAGLIST") {
|
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
m_spawnthing->emittername = ev->GetString(2);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (ev->NumArgs() == 3) {
|
|
|
|
m_spawnthing->endTag = ev->GetString(2);
|
|
|
|
m_spawnthing->emittername = ev->GetString(3);
|
|
|
|
} else if (ev->NumArgs() == 2) {
|
|
|
|
m_spawnthing->emittername = ev->GetString(2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_spawnthing->cgd.tiki = current_tiki;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndTagBeamEmitter
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndTagBeamEmitter(void) { endblockfcn = NULL; }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginOriginEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginOriginEmitter(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndOriginEmitter;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the emitter
|
|
|
|
m_spawnthing = CreateNewEmitter();
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the emitter's name
|
|
|
|
m_spawnthing->emittername = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!m_spawnthing->emittername.length()) {
|
|
|
|
warning("CCM::BeginOriginEmitter",
|
|
|
|
"Emittername not specified for originemitter in model: '%s'\n",
|
|
|
|
cgi.TIKI_Name(current_tiki));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.tiki = current_tiki;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// EndOriginEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndOriginEmitter(void) { endblockfcn = NULL; }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginOriginBeamEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginOriginBeamEmitter(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndOriginBeamEmitter;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the emitter
|
|
|
|
m_spawnthing = CreateNewEmitter();
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the emitter's name
|
|
|
|
m_spawnthing->emittername = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!m_spawnthing->emittername.length()) {
|
|
|
|
warning("CCM::BeginOriginEmitter",
|
|
|
|
"Emittername not specified for originemitter in model: '%s'\n",
|
|
|
|
cgi.TIKI_Name(current_tiki));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.tiki = current_tiki;
|
|
|
|
m_spawnthing->cgd.flags |= T_BEAMTHING;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// EndOriginBeamEmitter
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndOriginBeamEmitter(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
endblockfcn = NULL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// GetOrientation - Calculates the orientation of a tag
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::GetOrientation(int tagnum, spawnthing_t* sp)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
orientation_t or;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
assert(current_entity);
|
|
|
|
assert(current_tiki);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!current_entity || !current_tiki) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
or = cgi.TIKI_Orientation(current_entity, tagnum);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
VectorCopy(current_entity->origin, sp->cgd.origin);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
VectorMA(sp->cgd.origin, or.origin[i], current_entity->axis[i],
|
|
|
|
sp->cgd.origin);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
MatrixMultiply(or.axis, current_entity->axis, sp->axis);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// If angles are not set, then use the angles from the tag
|
|
|
|
if (!(sp->cgd.flags & T_ANGLES)) {
|
|
|
|
vectoangles(sp->axis[0], sp->cgd.angles);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
AxisCopy(sp->axis, sp->tag_axis);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 23:43:27 +02:00
|
|
|
void ClientGameCommandManager::BeginTagSpawnLinked(Event* ev)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginTagSpawn
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginTagSpawn(Event* ev)
|
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
int tagnum;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndTagSpawn;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the thing we are going to spawn
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the tagname and orientation
|
|
|
|
tagname = ev->GetString(1);
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist", tagname.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
GetOrientation(tagnum, m_spawnthing);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndTagSpawn
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndTagSpawn(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Okay we should have a valid spawnthing, let's create a render entity
|
|
|
|
SpawnTempModel(m_spawnthing->count);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// BeginTagBeamShoot
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::BeginTagBeamSpawn(Event* ev)
|
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
int tagnum;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndTagBeamSpawn;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the thing we are going to spawn
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the tagname and orientation
|
|
|
|
tagname = ev->GetString(1);
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist", tagname.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
GetOrientation(tagnum, m_spawnthing);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndTagSpawn
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndTagBeamSpawn(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Okay we should have a valid spawnthing, let's create the beam now
|
|
|
|
int i;
|
|
|
|
int renderfx;
|
|
|
|
Vector end;
|
|
|
|
trace_t trace;
|
|
|
|
float scale = 1.0f;
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
scale = current_entity->scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
m_spawnthing->cgd.origin += Vector(m_spawnthing->tag_axis[i])
|
|
|
|
* (m_spawnthing->axis_offset_base[i]
|
|
|
|
+ m_spawnthing->axis_offset_amplitude[i] * random());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_spawnthing->use_last_trace_end) {
|
|
|
|
end = last_trace_end;
|
|
|
|
} else {
|
|
|
|
end = m_spawnthing->cgd.origin +
|
|
|
|
Vector(m_spawnthing->axis[0]) * m_spawnthing->length +
|
|
|
|
Vector(m_spawnthing->axis[1]) * crandom() * m_spawnthing->spreadx +
|
|
|
|
Vector(m_spawnthing->axis[2]) * crandom() * m_spawnthing->spready;
|
|
|
|
last_trace_end = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_Trace(&trace, m_spawnthing->cgd.origin, vec_zero, vec_zero, end,
|
|
|
|
ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "EndTagBeamSpawn");
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
renderfx = (current_entity->renderfx &
|
|
|
|
~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
|
|
|
|
} else {
|
|
|
|
renderfx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_CreateBeam(m_spawnthing->cgd.origin, vec_zero, current_entity_number, 1,
|
|
|
|
m_spawnthing->cgd.alpha, m_spawnthing->cgd.scale * scale,
|
2023-04-30 00:02:16 +02:00
|
|
|
(m_spawnthing->beamflags | BEAM_LIGHTNING_EFFECT),
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->length, m_spawnthing->cgd.life, qfalse,
|
|
|
|
trace.endpos, m_spawnthing->min_offset,
|
|
|
|
m_spawnthing->max_offset, m_spawnthing->overlap,
|
|
|
|
m_spawnthing->numSubdivisions, m_spawnthing->delay,
|
|
|
|
m_spawnthing->cgd.shadername, m_spawnthing->cgd.color,
|
|
|
|
m_spawnthing->numspherebeams, m_spawnthing->sphereRadius,
|
|
|
|
m_spawnthing->toggledelay, m_spawnthing->endalpha, renderfx,
|
|
|
|
m_spawnthing->emittername);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//===============
|
|
|
|
// BeginOriginBeamSpawn
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::BeginOriginBeamSpawn(Event* ev)
|
|
|
|
{
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Init the emitter
|
|
|
|
m_spawnthing = CreateNewEmitter();
|
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the origin based on the entity's origin
|
|
|
|
m_spawnthing->cgd.origin = current_entity->origin;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Set the axis based on the entity's axis
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->axis);
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->tag_axis);
|
|
|
|
MatrixToEulerAngles(m_spawnthing->axis, m_spawnthing->cgd.angles);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Setup ending function
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndOriginBeamSpawn;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// EndOriginBeamSpawn
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EndOriginBeamSpawn(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Okay we should have a valid spawnthing, let's create the beam now
|
|
|
|
int i, renderfx, c, count;
|
|
|
|
Vector end;
|
|
|
|
trace_t trace;
|
|
|
|
float scale = 1.0f;
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
scale = current_entity->scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = m_spawnthing->count * cg_effectdetail->value;
|
|
|
|
|
|
|
|
for (c = 0; c <= count; c++) {
|
|
|
|
Vector angles;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
// Randomize angles or set absolute
|
|
|
|
angles[i] = m_spawnthing->cgd.angles[i] +
|
|
|
|
random() * m_spawnthing->angles_amplitude[i];
|
|
|
|
|
|
|
|
m_spawnthing->cgd.origin +=
|
|
|
|
Vector(m_spawnthing->tag_axis[i]) *
|
|
|
|
(m_spawnthing->axis_offset_base[i] +
|
|
|
|
m_spawnthing->axis_offset_amplitude[i] * random());
|
|
|
|
}
|
|
|
|
|
|
|
|
AnglesToAxis(angles, m_spawnthing->axis);
|
|
|
|
end = m_spawnthing->cgd.origin +
|
|
|
|
Vector(m_spawnthing->axis[0]) * m_spawnthing->length +
|
|
|
|
Vector(m_spawnthing->axis[1]) * crandom() * m_spawnthing->spreadx +
|
|
|
|
Vector(m_spawnthing->axis[2]) * crandom() * m_spawnthing->spready;
|
|
|
|
|
|
|
|
CG_Trace(&trace, m_spawnthing->cgd.origin, vec_zero, vec_zero, end,
|
|
|
|
ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue,
|
|
|
|
"EndOriginBeamSpawn");
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
renderfx = (current_entity->renderfx &
|
|
|
|
~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
|
|
|
|
} else {
|
|
|
|
renderfx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_CreateBeam(
|
|
|
|
m_spawnthing->cgd.origin, vec_zero, current_entity_number, 1,
|
|
|
|
m_spawnthing->cgd.alpha, m_spawnthing->cgd.scale * scale,
|
|
|
|
(m_spawnthing->beamflags | BEAM_LIGHTNING_EFFECT),
|
|
|
|
m_spawnthing->length, m_spawnthing->cgd.life, qtrue, trace.endpos,
|
|
|
|
m_spawnthing->min_offset, m_spawnthing->max_offset,
|
|
|
|
m_spawnthing->overlap, m_spawnthing->numSubdivisions,
|
|
|
|
m_spawnthing->delay, m_spawnthing->cgd.shadername,
|
|
|
|
m_spawnthing->cgd.color, m_spawnthing->numspherebeams,
|
|
|
|
m_spawnthing->sphereRadius, m_spawnthing->toggledelay,
|
|
|
|
m_spawnthing->endalpha, renderfx, m_spawnthing->emittername);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// AllocateTempModel
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
ctempmodel_t* ClientGameCommandManager::AllocateTempModel(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
ctempmodel_t* p;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!m_free_tempmodels) {
|
|
|
|
// no free entities, so free the one at the end of the chain
|
|
|
|
// remove the oldest active entity
|
|
|
|
FreeTempModel(m_active_tempmodels.prev);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
p = m_free_tempmodels;
|
|
|
|
m_free_tempmodels = m_free_tempmodels->next;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// link into the active list
|
|
|
|
p->next = m_active_tempmodels.next;
|
|
|
|
p->prev = &m_active_tempmodels;
|
|
|
|
m_active_tempmodels.next->prev = p;
|
|
|
|
m_active_tempmodels.next = p;
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// FreeTempModel
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::FreeTempModel(ctempmodel_t* p)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
if (!p->prev) {
|
|
|
|
cgi.Error(ERR_DROP, "CCM::FreeTempModel: not active");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
RemoveClientEntity(p->number, p->cgd.tiki, NULL, p);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// remove from the doubly linked active list
|
|
|
|
p->prev->next = p->next;
|
|
|
|
p->next->prev = p->prev;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// the free list is only singly linked
|
|
|
|
p->next = m_free_tempmodels;
|
|
|
|
m_free_tempmodels = p;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::ResetTempModels(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
// Go through all the active tempmodels and free them
|
|
|
|
ctempmodel_t *p, *next;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
p = m_active_tempmodels.prev;
|
|
|
|
for (; p != &m_active_tempmodels; p = next) {
|
|
|
|
next = p->prev;
|
|
|
|
FreeTempModel(p);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// InitializeTempModels
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::InitializeTempModels(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int numtempmodels = MAX_TEMPMODELS;
|
|
|
|
|
|
|
|
m_active_tempmodels.next = &m_active_tempmodels;
|
|
|
|
m_active_tempmodels.prev = &m_active_tempmodels;
|
|
|
|
|
|
|
|
m_free_tempmodels = &m_tempmodels[0];
|
|
|
|
|
|
|
|
for (i = 0; i < numtempmodels - 1; i++) {
|
|
|
|
m_tempmodels[i].next = &m_tempmodels[i + 1];
|
|
|
|
}
|
|
|
|
m_tempmodels[numtempmodels - 1].next = NULL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-01 17:06:15 +02:00
|
|
|
void ClientGameCommandManager::InitializeTempModelCvars(void)
|
|
|
|
{
|
|
|
|
cg_showtempmodels = cgi.Cvar_Get("cg_showtempmodels", "0", 0);
|
|
|
|
cg_detail = cgi.Cvar_Get("detail", "1", 1);
|
|
|
|
cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", 1);
|
|
|
|
cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", 1);
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
// InitializeEmitters
|
2023-04-30 00:02:16 +02:00
|
|
|
//=============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::InitializeEmitters(void) {}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//===============
|
|
|
|
// UpdateSwarm
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::UpdateSwarm(ctempmodel_t* p)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (p->cgd.swarmfreq == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the frequency is hit, set a new velocity
|
|
|
|
if (!(rand() % p->cgd.swarmfreq)) {
|
|
|
|
p->cgd.velocity.x = crandom() * p->cgd.swarmmaxspeed;
|
|
|
|
p->cgd.velocity.y = crandom() * p->cgd.swarmmaxspeed;
|
|
|
|
p->cgd.velocity.z = crandom() * p->cgd.swarmmaxspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to move toward the origin by the specified delta
|
|
|
|
if (p->cgd.origin.x < p->cgd.parentOrigin.x) {
|
|
|
|
p->cgd.velocity.x += p->cgd.swarmdelta;
|
|
|
|
} else {
|
|
|
|
p->cgd.velocity.x -= p->cgd.swarmdelta;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.origin.y < p->cgd.parentOrigin.y) {
|
|
|
|
p->cgd.velocity.y += p->cgd.swarmdelta;
|
|
|
|
} else {
|
|
|
|
p->cgd.velocity.y -= p->cgd.swarmdelta;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.origin.z < p->cgd.parentOrigin.z) {
|
|
|
|
p->cgd.velocity.z += p->cgd.swarmdelta;
|
|
|
|
} else {
|
|
|
|
p->cgd.velocity.z -= p->cgd.swarmdelta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::OtherTempModelEffects(ctempmodel_t* p,
|
|
|
|
Vector origin,
|
|
|
|
refEntity_t* newEnt)
|
|
|
|
|
|
|
|
{
|
|
|
|
vec3_t axis[3];
|
|
|
|
|
|
|
|
if (p->number != -1) {
|
|
|
|
// Set the axis
|
|
|
|
AnglesToAxis(p->cgd.angles, axis);
|
|
|
|
|
|
|
|
current_scale = newEnt->scale;
|
|
|
|
current_entity = newEnt;
|
|
|
|
current_tiki = p->cgd.tiki;
|
|
|
|
current_entity_number = p->number;
|
|
|
|
|
|
|
|
// Update any emitters that are active on this tempmodel
|
|
|
|
UpdateEmitter(p->cgd.tiki, axis, p->number, p->cgd.parent,
|
|
|
|
origin);
|
|
|
|
|
|
|
|
// Add in trails for this tempmodel
|
|
|
|
if (p->cgd.flags2 & T2_TRAIL) {
|
|
|
|
Event* ev = new Event(EV_Client_Swipe);
|
|
|
|
ev->AddVector(origin);
|
|
|
|
commandManager.ProcessEvent(ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity_number = -1;
|
|
|
|
current_tiki = NULL;
|
|
|
|
current_entity = NULL;
|
|
|
|
current_scale = -1;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// AnimateTempModel - animate temp models
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::AnimateTempModel(ctempmodel_t* p, Vector origin,
|
|
|
|
refEntity_t* newEnt)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int numframes;
|
|
|
|
int deltatime;
|
|
|
|
int frametime;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// This code is for animating tempmodels that are spawned from the client
|
|
|
|
// side
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-04 21:07:33 +02:00
|
|
|
if (!p->cgd.tiki) {
|
2023-04-30 20:20:58 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Calc frame stuff
|
|
|
|
frametime = 1000.0f * cgi.Anim_Frametime(p->cgd.tiki, p->ent.frameInfo[0].index);
|
|
|
|
deltatime = cg.time - p->lastAnimTime;
|
|
|
|
numframes = cgi.Anim_NumFrames(p->cgd.tiki, p->ent.frameInfo[0].index);
|
|
|
|
|
|
|
|
if (!p->addedOnce) {
|
|
|
|
// Process entry commands
|
|
|
|
CG_ProcessEntityCommands(TIKI_FRAME_ENTRY,
|
|
|
|
p->ent.frameInfo[0].index, -1, &p->ent, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numframes < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go through all the frames, and process any commands associated with the
|
|
|
|
// tempmodel as well
|
|
|
|
while (deltatime >= frametime) {
|
|
|
|
p->lastAnimTime += frametime;
|
|
|
|
p->ent.wasframe = (p->ent.wasframe + 1) % numframes;
|
|
|
|
CG_ProcessEntityCommands(p->ent.wasframe, p->ent.frameInfo[0].index,
|
|
|
|
-1, &p->ent, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t* p,
|
|
|
|
float ftime,
|
|
|
|
float dtime,
|
|
|
|
float scale)
|
|
|
|
|
|
|
|
{
|
|
|
|
float fade, fadein;
|
|
|
|
byte tempColor[4];
|
|
|
|
|
|
|
|
if (p->cgd.flags & (T_FADE | T_SCALEUPDOWN)) {
|
|
|
|
fade = 1.0f - (float)(p->aliveTime - p->cgd.fadedelay) /
|
|
|
|
(float)(p->cgd.life - p->cgd.fadedelay);
|
|
|
|
|
|
|
|
// Clamp the fade
|
|
|
|
if (fade > 1) {
|
|
|
|
fade = 1;
|
|
|
|
}
|
|
|
|
if (fade < 0) {
|
|
|
|
fade = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fade = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
dtime = (cg.time - p->cgd.createTime);
|
|
|
|
|
|
|
|
// Calculate fade in value
|
|
|
|
if (p->cgd.flags & T_FADEIN) {
|
|
|
|
fadein = dtime / (float)p->cgd.fadeintime;
|
|
|
|
} else {
|
|
|
|
fadein = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert dtime to seconds
|
|
|
|
dtime *= 0.001f;
|
|
|
|
|
|
|
|
// Do the scale animation
|
|
|
|
if (ftime && p->cgd.scaleRate) {
|
|
|
|
p->ent.scale += p->ent.scale * (p->cgd.scaleRate * ftime);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_SCALEUPDOWN) {
|
|
|
|
p->ent.scale = p->cgd.scale * sin((fade)*M_PI);
|
|
|
|
|
|
|
|
if (p->ent.scale < p->cgd.scalemin) {
|
|
|
|
p->ent.scale = p->cgd.scalemin;
|
|
|
|
}
|
|
|
|
if (p->ent.scale > p->cgd.scalemax) {
|
|
|
|
p->ent.scale = p->cgd.scalemax;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.lightstyle >= 0) {
|
|
|
|
int i;
|
|
|
|
float color[4];
|
|
|
|
CG_LightStyleColor(p->cgd.lightstyle, dtime * 1000, color);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
tempColor[i] = color[i] * 255;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
memcpy(tempColor, p->cgd.color, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_TWINKLE) {
|
|
|
|
// See if we should toggle the twinkle
|
|
|
|
if (cg.time > p->twinkleTime) {
|
|
|
|
// If off, turn it on
|
|
|
|
if (p->cgd.flags & T_TWINKLE_OFF) {
|
|
|
|
p->cgd.flags &= ~T_TWINKLE_OFF;
|
|
|
|
p->twinkleTime = cg.time + p->cgd.min_twinkletimeon +
|
|
|
|
random() * p->cgd.max_twinkletimeon;
|
|
|
|
} else {
|
|
|
|
p->cgd.flags |= T_TWINKLE_OFF;
|
|
|
|
p->twinkleTime = cg.time + p->cgd.min_twinkletimeoff +
|
|
|
|
random() * p->cgd.max_twinkletimeoff;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_TWINKLE_OFF) {
|
|
|
|
memset(tempColor, 0, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_FADEIN && (fadein < 1)) // Do the fadein effect
|
|
|
|
{
|
|
|
|
p->ent.shaderRGBA[0] = (int)(tempColor[0] * (fadein * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[1] = (int)(tempColor[1] * (fadein * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[2] = (int)(tempColor[2] * (fadein * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[3] = (int)(tempColor[3] * (fadein * p->cgd.alpha));
|
|
|
|
} else if (p->cgd.flags & T_FADE) // Do a fadeout effect
|
|
|
|
{
|
|
|
|
p->ent.shaderRGBA[0] = (tempColor[0] * (fade * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[1] = (tempColor[1] * (fade * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[2] = (tempColor[2] * (fade * p->cgd.alpha));
|
|
|
|
p->ent.shaderRGBA[3] = (tempColor[3] * (fade * p->cgd.alpha));
|
|
|
|
} else {
|
|
|
|
p->ent.shaderRGBA[0] = tempColor[0] * p->cgd.alpha;
|
|
|
|
p->ent.shaderRGBA[1] = tempColor[1] * p->cgd.alpha;
|
|
|
|
p->ent.shaderRGBA[2] = tempColor[2] * p->cgd.alpha;
|
|
|
|
p->ent.shaderRGBA[3] = tempColor[3] * p->cgd.alpha;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_FLICKERALPHA) {
|
|
|
|
float random = random();
|
|
|
|
|
|
|
|
if (p->cgd.flags & (T_FADE | T_FADEIN)) {
|
|
|
|
p->ent.shaderRGBA[0] *= random;
|
|
|
|
p->ent.shaderRGBA[1] *= random;
|
|
|
|
p->ent.shaderRGBA[2] *= random;
|
|
|
|
p->ent.shaderRGBA[3] *= random;
|
|
|
|
} else {
|
|
|
|
p->ent.shaderRGBA[0] = p->cgd.color[0] * random;
|
|
|
|
p->ent.shaderRGBA[1] = p->cgd.color[1] * random;
|
|
|
|
p->ent.shaderRGBA[2] = p->cgd.color[2] * random;
|
|
|
|
p->ent.shaderRGBA[3] = p->cgd.color[3] * random;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for completely faded out model
|
|
|
|
if (fade <= 0 && p->addedOnce) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for completely scaled out model
|
|
|
|
if ((p->ent.scale <= 0 && p->addedOnce) &&
|
|
|
|
!(p->cgd.flags & T_SCALEUPDOWN)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do swarming flies effects
|
|
|
|
if (p->cgd.flags & T_SWARM) {
|
|
|
|
UpdateSwarm(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t* p,
|
|
|
|
float ftime, float time2,
|
|
|
|
float scale)
|
|
|
|
|
|
|
|
{
|
|
|
|
int dtime;
|
|
|
|
Vector parentOrigin(0, 0, 0);
|
|
|
|
Vector parentAngles(0, 0, 0);
|
|
|
|
Vector tempangles;
|
|
|
|
trace_t trace;
|
|
|
|
float dot;
|
|
|
|
|
|
|
|
VectorCopy(p->ent.origin, p->lastEnt.origin);
|
|
|
|
AxisCopy(p->ent.axis, p->lastEnt.axis);
|
|
|
|
|
|
|
|
dtime = (cg.time - p->cgd.createTime);
|
|
|
|
|
|
|
|
// Save oldorigin
|
|
|
|
p->cgd.oldorigin = p->cgd.origin;
|
|
|
|
|
|
|
|
// Update the orign and the angles based on velocities first
|
|
|
|
if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) {
|
|
|
|
p->cgd.origin = p->cgd.origin + (p->cgd.velocity * ftime * scale) +
|
|
|
|
(time2 * p->cgd.accel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If linked to the parent or hardlinked, get the parent's origin
|
|
|
|
if ((p->cgd.flags & (T_PARENTLINK | T_HARDLINK)) &&
|
|
|
|
(p->cgd.parent != ENTITYNUM_NONE)) {
|
|
|
|
centity_t* pc;
|
|
|
|
pc = &cg_entities[p->cgd.parent];
|
|
|
|
|
|
|
|
if (pc->currentValid) {
|
|
|
|
refEntity_t* e;
|
|
|
|
|
|
|
|
e = cgi.R_GetRenderEntity(p->cgd.parent);
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
return false;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
parentOrigin = e->origin;
|
|
|
|
vectoangles(e->axis[0], parentAngles);
|
|
|
|
} else {
|
2023-04-30 00:02:16 +02:00
|
|
|
return false;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Align the object along it's traveling vector
|
|
|
|
if (p->cgd.flags & T_ALIGN) {
|
|
|
|
p->cgd.angles = p->cgd.velocity.toAngles();
|
|
|
|
parentAngles = vec_zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_RANDOMROLL) {
|
|
|
|
p->cgd.angles[ROLL] = random() * 360;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the angles based on angular velocity
|
|
|
|
if (p->cgd.flags2 & T2_AMOVE) {
|
|
|
|
p->cgd.angles = p->cgd.angles + (ftime * p->cgd.avelocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mod the angles if needed
|
|
|
|
p->cgd.angles[0] = AngleMod(p->cgd.angles[0]);
|
|
|
|
p->cgd.angles[1] = AngleMod(p->cgd.angles[1]);
|
|
|
|
p->cgd.angles[2] = AngleMod(p->cgd.angles[2]);
|
|
|
|
|
|
|
|
// Add in parent angles
|
|
|
|
tempangles = p->cgd.angles + parentAngles;
|
|
|
|
|
|
|
|
// Convert to axis
|
|
|
|
if ((p->cgd.flags &
|
|
|
|
(T_ALIGN | T_RANDOMROLL | T_PARENTLINK | T_HARDLINK | T_ANGLES)) ||
|
|
|
|
(p->cgd.flags2 & T2_AMOVE)) {
|
|
|
|
AnglesToAxis(tempangles, p->ent.axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only do real collision if necessary
|
|
|
|
if (p->cgd.flags & T_COLLISION) {
|
|
|
|
// trace a line from previous position to new position
|
2023-05-04 21:07:33 +02:00
|
|
|
CG_Trace(&trace, p->cgd.oldorigin, vec3_origin, vec3_origin, p->cgd.origin, -1,
|
2023-04-30 20:20:58 +02:00
|
|
|
p->cgd.collisionmask, qfalse, qfalse, "Collision");
|
|
|
|
} else {
|
|
|
|
// Fake it out so it never collides
|
|
|
|
trace.fraction = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for collision
|
|
|
|
if (trace.fraction == 1.0) {
|
|
|
|
// Acceleration of velocity
|
|
|
|
if (p->cgd.flags2 & T2_ACCEL) {
|
|
|
|
p->cgd.velocity = p->cgd.velocity + ftime * p->cgd.accel;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (p->touchfcn) {
|
|
|
|
p->touchfcn(p, &trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_DIETOUCH) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector normal;
|
|
|
|
|
|
|
|
// Set the origin
|
|
|
|
p->cgd.origin = trace.endpos;
|
|
|
|
|
|
|
|
if ((p->cgd.flags2 & T2_BOUNCE_DECAL) &&
|
|
|
|
(p->cgd.bouncecount < p->cgd.maxbouncecount)) {
|
|
|
|
// Put down a bounce decal
|
|
|
|
qhandle_t shader = cgi.R_RegisterShader(p->cgd.shadername);
|
|
|
|
|
|
|
|
CG_ImpactMark(shader, trace.endpos, trace.plane.normal,
|
|
|
|
p->cgd.decal_orientation,
|
|
|
|
(float)p->cgd.color[0] / 255.0f,
|
|
|
|
(float)p->cgd.color[1] / 255.0f,
|
|
|
|
(float)p->cgd.color[2] / 255.0f, p->cgd.alpha,
|
|
|
|
p->cgd.flags & T_FADE, p->cgd.decal_radius,
|
|
|
|
p->cgd.flags2 & T2_TEMPORARY_DECAL, p->cgd.lightstyle,
|
2023-05-01 00:10:07 +02:00
|
|
|
p->cgd.flags & T_FADEIN,
|
|
|
|
0.f,
|
|
|
|
0.f);
|
2023-04-30 20:20:58 +02:00
|
|
|
|
|
|
|
p->cgd.bouncecount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate the bounce
|
|
|
|
normal = trace.plane.normal;
|
|
|
|
|
|
|
|
// reflect the velocity on the trace plane
|
|
|
|
if (p->cgd.flags2 & T2_ACCEL) {
|
|
|
|
p->cgd.velocity =
|
|
|
|
p->cgd.velocity + ftime * trace.fraction * p->cgd.accel;
|
|
|
|
}
|
|
|
|
|
|
|
|
dot = p->cgd.velocity * normal;
|
|
|
|
p->cgd.velocity = p->cgd.velocity + ((-2 * dot) * normal);
|
|
|
|
p->cgd.velocity *= p->cgd.bouncefactor;
|
|
|
|
|
|
|
|
// check for stop
|
|
|
|
if (trace.plane.normal[2] > 0 && p->cgd.velocity[2] < 40) {
|
|
|
|
p->cgd.velocity = Vector(0, 0, 0);
|
|
|
|
p->cgd.avelocity = Vector(0, 0, 0);
|
|
|
|
p->cgd.flags &= ~T_WAVE;
|
|
|
|
} else {
|
|
|
|
if (p->cgd.flags & T_BOUNCESOUNDONCE) {
|
|
|
|
vec3_t org;
|
|
|
|
VectorCopy(p->cgd.origin, org);
|
2023-05-04 20:30:02 +02:00
|
|
|
PlaySound(p->cgd.bouncesound, org);
|
2023-04-30 20:20:58 +02:00
|
|
|
p->cgd.flags &= ~(T_BOUNCESOUNDONCE | T_BOUNCESOUND);
|
|
|
|
} else if ((p->cgd.flags & T_BOUNCESOUND) &&
|
|
|
|
(p->next_bouncesound_time < cg.time)) {
|
|
|
|
vec3_t org;
|
|
|
|
VectorCopy(p->cgd.origin, org);
|
2023-05-04 20:30:02 +02:00
|
|
|
PlaySound(p->cgd.bouncesound, org);
|
2023-04-30 20:20:58 +02:00
|
|
|
p->next_bouncesound_time = cg.time + p->cgd.bouncesound_delay;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy over origin
|
|
|
|
VectorCopy(p->cgd.origin, p->ent.origin);
|
|
|
|
|
|
|
|
// Add in parent's origin if linked
|
|
|
|
if (p->cgd.flags & (T_PARENTLINK | T_HARDLINK)) {
|
|
|
|
VectorAdd(p->ent.origin, parentOrigin, p->ent.origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p->lastEntValid) {
|
|
|
|
// Make the lastEnt valid, by setting it to p->ent and setting the
|
|
|
|
// origin to the tempmodel's oldorigin
|
|
|
|
p->lastEnt = p->ent;
|
|
|
|
VectorCopy(p->cgd.oldorigin, p->lastEnt.origin);
|
|
|
|
p->lastEntValid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean ClientGameCommandManager::LerpTempModel(refEntity_t* newEnt,
|
|
|
|
ctempmodel_t* p, float frac)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
// If the tempmodel is parentlinked, then we need to get the origin of the
|
|
|
|
// parent and add it to the tempmodel's origin
|
|
|
|
if (p->cgd.flags & (T_PARENTLINK | T_HARDLINK)) {
|
|
|
|
centity_t* pc;
|
|
|
|
Vector parentOrigin;
|
|
|
|
|
|
|
|
// Lerp the tempmodel's local origin
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
newEnt->origin[i] = p->cgd.oldorigin[i] +
|
|
|
|
frac * (p->cgd.origin[i] - p->cgd.oldorigin[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the parent entity
|
|
|
|
pc = &cg_entities[p->cgd.parent];
|
|
|
|
|
|
|
|
if (pc->currentValid) {
|
|
|
|
refEntity_t* e;
|
|
|
|
|
|
|
|
e = cgi.R_GetRenderEntity(p->cgd.parent);
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
return false;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
parentOrigin = e->origin;
|
|
|
|
} else {
|
2023-04-30 00:02:16 +02:00
|
|
|
return false;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add the parent ent's origin to the local origin
|
|
|
|
VectorAdd(newEnt->origin, parentOrigin, newEnt->origin);
|
|
|
|
} else {
|
|
|
|
if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) {
|
|
|
|
// Lerp the ent's origin
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
newEnt->origin[i] =
|
|
|
|
p->lastEnt.origin[i] +
|
|
|
|
frac * (p->ent.origin[i] - p->lastEnt.origin[i]);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (p->cgd.flags2 & T2_PARALLEL) {
|
|
|
|
Vector v1 = p->cgd.origin - cg.refdef.vieworg;
|
|
|
|
vectoangles(v1, p->cgd.angles);
|
|
|
|
AnglesToAxis(p->cgd.angles, newEnt->axis);
|
|
|
|
} else if ((p->cgd.flags &
|
|
|
|
(T_ALIGN | T_RANDOMROLL | T_PARENTLINK | T_HARDLINK)) ||
|
|
|
|
(p->cgd.flags2 & T2_AMOVE)) {
|
|
|
|
// Lerp axis
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
for (j = 0; j < 3; j++) {
|
|
|
|
newEnt->axis[i][j] =
|
|
|
|
p->lastEnt.axis[i][j] +
|
|
|
|
frac * (p->ent.axis[i][j] - p->lastEnt.axis[i][j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
static int lastTempModelFrameTime = 0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// AddTempModels - Update and add tempmodels to the ref
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
#define TOO_MUCH_TIME_PASSED 500
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::AddTempModels(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
ctempmodel_t *p, *next;
|
|
|
|
int count = 0; // Tempmodel count
|
|
|
|
int frameTime;
|
|
|
|
float effectTime, effectTime2;
|
|
|
|
int mstime = 0;
|
|
|
|
float ftime = 0;
|
|
|
|
float time2 = 0;
|
|
|
|
float scale = 1.0f;
|
|
|
|
float lerpfrac = 0;
|
|
|
|
int physics_rate = 0;
|
|
|
|
qboolean ret;
|
|
|
|
refEntity_t newEnt;
|
|
|
|
dtiki_t* old_tiki;
|
|
|
|
int old_num;
|
|
|
|
refEntity_t* old_ent;
|
|
|
|
|
|
|
|
// To counteract cg.time going backwards
|
|
|
|
if (lastTempModelFrameTime) {
|
|
|
|
if ((cg.time < lastTempModelFrameTime) ||
|
|
|
|
(cg.time - lastTempModelFrameTime > TOO_MUCH_TIME_PASSED)) {
|
|
|
|
p = m_active_tempmodels.prev;
|
|
|
|
for (; p != &m_active_tempmodels; p = next) {
|
|
|
|
next = p->prev;
|
|
|
|
p->lastPhysicsTime = cg.time;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
lastTempModelFrameTime = cg.time;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastTempModelFrameTime != 0) {
|
|
|
|
frameTime = cg.time - lastTempModelFrameTime;
|
|
|
|
} else {
|
|
|
|
frameTime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (paused->integer) {
|
|
|
|
lastTempModelFrameTime = 0;
|
|
|
|
} else {
|
|
|
|
lastTempModelFrameTime = cg.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&newEnt, 0, sizeof(newEnt));
|
|
|
|
// Set this frame time for the next one
|
|
|
|
effectTime = (float)frameTime / 1000.0f;
|
|
|
|
effectTime2 = effectTime * effectTime;
|
|
|
|
|
|
|
|
// If there is a current entity, it's scale is used as a factor
|
|
|
|
if (current_entity) {
|
|
|
|
scale = current_entity->scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go through all the temp models and run the physics if necessary,
|
|
|
|
// then add them to the ref
|
|
|
|
old_ent = current_entity;
|
|
|
|
old_tiki = current_tiki;
|
|
|
|
old_num = current_entity_number;
|
|
|
|
|
|
|
|
p = m_active_tempmodels.prev;
|
|
|
|
for (; p != &m_active_tempmodels; p = next) {
|
|
|
|
// grab next now, so if the local entity is freed we still have it
|
|
|
|
next = p->prev;
|
|
|
|
|
|
|
|
if ((p->cgd.flags & T_DETAIL) && !cg_detail->integer) {
|
|
|
|
FreeTempModel(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->ent.tiki = p->cgd.tiki;
|
|
|
|
current_entity = &p->ent;
|
|
|
|
current_tiki = p->cgd.tiki;
|
|
|
|
current_entity_number = p->number;
|
|
|
|
|
|
|
|
TempModelRealtimeEffects(p, effectTime, effectTime2, scale);
|
|
|
|
|
|
|
|
if (p->lastPhysicsTime) {
|
|
|
|
mstime = cg.time - p->lastPhysicsTime;
|
|
|
|
|
|
|
|
// Check for physics
|
|
|
|
physics_rate =
|
|
|
|
1000 / p->cgd.physicsRate; // Physics rate in milliseconds
|
|
|
|
|
|
|
|
// Avoid large jumps in time
|
|
|
|
if (mstime > physics_rate * 2) {
|
|
|
|
mstime = physics_rate;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if ((mstime >= physics_rate) ||
|
|
|
|
(p->cgd.flags2 & T2_PHYSICS_EVERYFRAME)) {
|
|
|
|
ftime = mstime / 1000.0f;
|
|
|
|
time2 = ftime * ftime;
|
|
|
|
ret = TempModelPhysics(p, ftime, time2, scale);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!ret) {
|
|
|
|
FreeTempModel(p);
|
|
|
|
continue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
p->lastPhysicsTime = cg.time;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the lerp value based on the time passed since last physics
|
|
|
|
// time of this tempmodel
|
|
|
|
lerpfrac = (float)(cg.time - p->lastPhysicsTime) / (float)physics_rate;
|
|
|
|
|
|
|
|
// Clamp
|
|
|
|
if (lerpfrac > 1) {
|
|
|
|
lerpfrac = 1;
|
|
|
|
}
|
|
|
|
if (lerpfrac < 0) {
|
|
|
|
lerpfrac = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment the time this tempmodel has been alive
|
|
|
|
p->aliveTime += frameTime;
|
|
|
|
|
|
|
|
// Dead, and free up the tempmodel
|
|
|
|
if (p->aliveTime >= p->cgd.life && p->addedOnce) {
|
|
|
|
FreeTempModel(p);
|
2023-04-30 00:02:16 +02:00
|
|
|
continue;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Run physics if the lastEnt is not valid to get a valid lerp
|
|
|
|
if (!p->lastEntValid) {
|
|
|
|
float t, t2;
|
|
|
|
t = physics_rate / 1000.0f;
|
|
|
|
t2 = t * t;
|
|
|
|
|
|
|
|
ret = TempModelPhysics(p, t, t2, scale);
|
|
|
|
if (!ret) {
|
|
|
|
FreeTempModel(p);
|
|
|
|
continue;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
lerpfrac = 0;
|
|
|
|
p->lastPhysicsTime = cg.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear out the new entity and initialize it
|
|
|
|
// this will become the current_entity if anything is spawned off it
|
|
|
|
|
|
|
|
newEnt.scale = p->ent.scale;
|
|
|
|
memcpy(newEnt.shaderRGBA, p->ent.shaderRGBA, 4);
|
|
|
|
AxisCopy(p->ent.axis, newEnt.axis);
|
|
|
|
VectorCopy(p->ent.origin, newEnt.origin);
|
|
|
|
|
|
|
|
// Lerp the tempmodel
|
|
|
|
if (!LerpTempModel(&newEnt, p, lerpfrac)) {
|
|
|
|
FreeTempModel(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_WAVE) {
|
|
|
|
Vector origin;
|
|
|
|
float axis[3][3];
|
|
|
|
|
|
|
|
origin = Vector(m_spawnthing->linked_origin) +
|
|
|
|
Vector(m_spawnthing->linked_axis[0]) * newEnt.origin[0] +
|
|
|
|
Vector(m_spawnthing->linked_axis[1]) * newEnt.origin[1] +
|
|
|
|
Vector(m_spawnthing->linked_axis[2]) * newEnt.origin[2];
|
|
|
|
|
|
|
|
VectorCopy(origin, newEnt.origin);
|
|
|
|
|
|
|
|
MatrixMultiply(newEnt.axis, p->m_spawnthing->linked_axis, axis);
|
|
|
|
AxisCopy(axis, newEnt.axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Animate and do trails (swipes)
|
|
|
|
newEnt.renderfx = p->ent.renderfx;
|
|
|
|
newEnt.hModel = p->ent.hModel;
|
|
|
|
newEnt.reType = p->ent.reType;
|
|
|
|
newEnt.shaderTime = p->ent.shaderTime;
|
|
|
|
|
|
|
|
newEnt.frameInfo[0] = p->ent.frameInfo[0];
|
|
|
|
newEnt.wasframe = p->ent.wasframe;
|
|
|
|
newEnt.actionWeight = 1.0;
|
|
|
|
newEnt.entityNumber = ENTITYNUM_NONE;
|
|
|
|
newEnt.tiki = p->ent.tiki;
|
|
|
|
|
|
|
|
AnimateTempModel(p, newEnt.origin, &newEnt);
|
|
|
|
|
|
|
|
OtherTempModelEffects(p, newEnt.origin, &newEnt);
|
|
|
|
|
|
|
|
// Add to the ref
|
|
|
|
if (p->cgd.flags & T_DLIGHT) {
|
|
|
|
// Tempmodel is a Dynamic Light
|
|
|
|
cgi.R_AddLightToScene(p->cgd.origin, p->cgd.lightIntensity * scale,
|
|
|
|
(float)p->cgd.color[0] / 255.0f,
|
|
|
|
(float)p->cgd.color[1] / 255.0f,
|
|
|
|
(float)p->cgd.color[2] / 255.0f,
|
|
|
|
p->cgd.lightType);
|
|
|
|
} else if (p->ent.reType == RT_SPRITE) {
|
|
|
|
vec3_t vTestAngles;
|
|
|
|
cgi.R_AddRefSpriteToScene(&newEnt); // Sprite
|
|
|
|
MatrixToEulerAngles(newEnt.axis, vTestAngles);
|
|
|
|
} else {
|
2023-05-01 17:28:14 +02:00
|
|
|
cgi.R_AddRefEntityToScene(&newEnt, ENTITYNUM_NONE); // Model
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set the added once flag so we can delete it later
|
|
|
|
p->addedOnce = qtrue;
|
|
|
|
|
|
|
|
// Local tempmodel count stat
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity = old_ent;
|
|
|
|
current_tiki = old_tiki;
|
|
|
|
current_entity_number = old_num;
|
|
|
|
|
|
|
|
// stats
|
|
|
|
if (cg_showtempmodels->integer) {
|
|
|
|
cgi.DPrintf("TC:%i\n", count);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// SpawnTempModel
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SpawnTempModel(int count, spawnthing_t* sp)
|
|
|
|
{
|
|
|
|
m_spawnthing = sp;
|
|
|
|
SpawnTempModel(count);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// SpawnTempModel
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::SpawnTempModel(int mcount, int timeAlive)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ctempmodel_t* p;
|
|
|
|
refEntity_t ent;
|
|
|
|
int count;
|
|
|
|
float current_entity_scale = 1.0f;
|
|
|
|
Vector newForward;
|
|
|
|
Vector delta;
|
|
|
|
Vector start;
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
current_entity_scale = current_entity->scale;
|
|
|
|
} else {
|
|
|
|
current_entity_scale = 1.0f;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (current_scale > 0) {
|
|
|
|
current_entity_scale *= current_scale;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (mcount > 1) {
|
|
|
|
mcount *= cg_effectdetail->value;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (mcount < 1) {
|
|
|
|
mcount = 1;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (count = 0; count < mcount; count++) {
|
|
|
|
p = AllocateTempModel();
|
|
|
|
|
|
|
|
if (!p) {
|
|
|
|
cgi.DPrintf("Out of tempmodels\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&ent, 0, sizeof(refEntity_t));
|
|
|
|
memset(&p->lastEnt, 0, sizeof(refEntity_t));
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_WAVE)
|
|
|
|
{
|
|
|
|
p->m_spawnthing = m_spawnthing;
|
|
|
|
start = Vector(0, 0, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->m_spawnthing = NULL;
|
|
|
|
start = m_spawnthing->cgd.origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy over the common data block
|
|
|
|
p->cgd = m_spawnthing->cgd;
|
|
|
|
|
|
|
|
// newForward may be changed by spehere or circle
|
|
|
|
newForward = m_spawnthing->axis[0];
|
|
|
|
|
|
|
|
// Set up the origin of the tempmodel
|
|
|
|
if (m_spawnthing->cgd.flags & T_SPHERE) {
|
|
|
|
// Create a random forward vector so the particles burst out in a
|
|
|
|
// sphere
|
|
|
|
newForward = Vector(crandom(), crandom(), crandom());
|
|
|
|
} else if (m_spawnthing->cgd.flags & T_CIRCLE) {
|
|
|
|
if (m_spawnthing->sphereRadius != 0) // Offset by the radius
|
2023-04-30 00:02:16 +02:00
|
|
|
{
|
2023-04-30 20:20:58 +02:00
|
|
|
Vector dst;
|
|
|
|
// Create a circular shaped burst around the up vector
|
|
|
|
float angle = ((float)count / (float)m_spawnthing->count) *
|
|
|
|
360; // * M_PI * 2;
|
|
|
|
|
|
|
|
Vector end = Vector(m_spawnthing->axis[1]) *
|
|
|
|
m_spawnthing->sphereRadius * current_entity_scale;
|
|
|
|
RotatePointAroundVector(dst, Vector(m_spawnthing->axis[0]), end, angle);
|
|
|
|
|
|
|
|
VectorAdd(dst, m_spawnthing->cgd.origin, p->cgd.origin);
|
|
|
|
newForward = p->cgd.origin - m_spawnthing->cgd.origin;
|
|
|
|
newForward.normalize();
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
} else if (m_spawnthing->cgd.flags & T_INWARDSPHERE) {
|
|
|
|
// Project the origin along a random ray, and set the forward
|
|
|
|
// vector pointing back to the origin
|
|
|
|
Vector dir, end;
|
|
|
|
|
|
|
|
dir = Vector(crandom(), crandom(), crandom());
|
|
|
|
|
|
|
|
end = m_spawnthing->cgd.origin +
|
|
|
|
dir * m_spawnthing->sphereRadius * current_entity_scale;
|
|
|
|
VectorCopy(end, p->cgd.origin);
|
|
|
|
newForward = dir * -1;
|
|
|
|
} else if (m_spawnthing->sphereRadius !=
|
|
|
|
0) // Offset in a spherical pattern
|
|
|
|
{
|
|
|
|
Vector dir, end;
|
|
|
|
|
|
|
|
dir = Vector(crandom(), crandom(), crandom());
|
|
|
|
|
|
|
|
dir.normalize();
|
|
|
|
|
|
|
|
end = m_spawnthing->cgd.origin +
|
|
|
|
dir * m_spawnthing->sphereRadius * current_entity_scale;
|
|
|
|
VectorCopy(end, p->cgd.origin);
|
|
|
|
newForward = dir;
|
|
|
|
} else {
|
|
|
|
VectorCopy(m_spawnthing->cgd.origin, p->cgd.origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Randomize the origin based on offsets
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
p->cgd.origin[i] += (random() * m_spawnthing->origin_offset_amplitude[i] + m_spawnthing->origin_offset_base[i]) *
|
|
|
|
current_entity_scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->cgd.oldorigin = p->cgd.origin;
|
|
|
|
p->modelname = m_spawnthing->GetModel();
|
|
|
|
p->addedOnce = qfalse;
|
|
|
|
p->lastEntValid = qfalse;
|
|
|
|
|
|
|
|
if (p->modelname.length()) {
|
|
|
|
ent.hModel = cgi.R_RegisterModel(p->modelname.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the refEntity
|
|
|
|
ent.shaderTime = cg.time / 1000.0f;
|
|
|
|
|
|
|
|
// Get the tikihandle
|
|
|
|
p->cgd.tiki = cgi.R_Model_GetHandle(ent.hModel);
|
|
|
|
|
|
|
|
// Set the reftype based on the modelname
|
|
|
|
if (p->modelname == "*beam") {
|
|
|
|
ent.reType = RT_BEAM;
|
|
|
|
ent.customShader = cgi.R_RegisterShader("beamshader");
|
|
|
|
} else if (strstr(p->modelname, ".spr")) {
|
|
|
|
ent.reType = RT_SPRITE;
|
|
|
|
} else {
|
|
|
|
ent.reType = RT_MODEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the animation
|
|
|
|
if (m_spawnthing->animName.length() && (p->cgd.tiki > 0)) {
|
|
|
|
ent.frameInfo[0].index =
|
|
|
|
cgi.Anim_NumForName(p->cgd.tiki, m_spawnthing->animName);
|
|
|
|
} else if (ent.reType == RT_MODEL && (p->cgd.tiki > 0)) {
|
|
|
|
ent.frameInfo[0].index = cgi.Anim_NumForName(p->cgd.tiki, "idle");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Randomize the scale
|
|
|
|
if (m_spawnthing->cgd.flags & T_RANDSCALE) // Check for random scale
|
|
|
|
{
|
|
|
|
ent.scale = RandomizeRange(m_spawnthing->cgd.scalemin,
|
|
|
|
m_spawnthing->cgd.scalemax);
|
|
|
|
p->cgd.scale = ent.scale;
|
|
|
|
} else {
|
|
|
|
ent.scale = m_spawnthing->cgd.scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
ent.scale *= current_entity_scale;
|
|
|
|
|
|
|
|
// CURRENT ENTITY INFLUENCES ON THE TEMPMODELS HAPPEN HERE
|
|
|
|
// copy over the renderfx from the current_entity, but only the flags we
|
|
|
|
// want
|
|
|
|
if (current_entity) {
|
|
|
|
// explicitly add RF_LIGHTING ORIGIN and RF_SHADOWPLANE because we
|
|
|
|
// don't want those on dynamic objects
|
|
|
|
ent.renderfx |= (current_entity->renderfx &
|
|
|
|
~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up modulation for constant color
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
p->cgd.color[i] = ent.shaderRGBA[i] = m_spawnthing->cgd.color[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply the alpha from the current_entity to the tempmodel
|
|
|
|
if (current_entity) {
|
|
|
|
float ealpha;
|
|
|
|
|
|
|
|
ealpha = (float)current_entity->shaderRGBA[3] / 255.0f;
|
|
|
|
|
|
|
|
if (ealpha != 1.0) {
|
|
|
|
// pre-multiply the alpha from the entity
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
p->cgd.color[i] = ent.shaderRGBA[i] =
|
|
|
|
ent.shaderRGBA[i] * ealpha;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
p->ent = ent;
|
|
|
|
p->lastEnt = ent;
|
|
|
|
p->number = -1;
|
|
|
|
|
|
|
|
// If createTime is specified, the use it. Otherwise use the createTime
|
|
|
|
// from the spawnthing.
|
|
|
|
if (timeAlive > 0) {
|
|
|
|
p->aliveTime = timeAlive;
|
|
|
|
} else {
|
|
|
|
p->aliveTime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If animateonce is set, set the life = to the length of the anim
|
|
|
|
if ((m_spawnthing->cgd.flags & T_ANIMATEONCE) &&
|
|
|
|
(p->ent.frameInfo[0].index > 0)) {
|
|
|
|
p->cgd.life =
|
|
|
|
cgi.Anim_Time(p->cgd.tiki, p->ent.frameInfo[0].index) * 1000.0f;
|
|
|
|
} else {
|
|
|
|
p->cgd.life = m_spawnthing->cgd.life;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->lastAnimTime = p->cgd.createTime;
|
|
|
|
p->lastPhysicsTime = p->cgd.createTime;
|
|
|
|
p->killTime = cg.time + p->cgd.life; // The time the tempmodel will die
|
|
|
|
p->seed = m_seed++; // For use with randomizations
|
|
|
|
p->cgd.velocity = Vector(0, 0, 0); // Zero out the velocity
|
|
|
|
p->next_bouncesound_time = 0; // Init the next bouncesound time
|
|
|
|
|
|
|
|
if (p->cgd.flags & T_TWINKLE) {
|
|
|
|
if (random() > 0.5f) {
|
|
|
|
p->cgd.flags |= T_TWINKLE_OFF;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags2 & T2_TRAIL) {
|
|
|
|
// Assign a global number to this entity from the
|
|
|
|
// command_time_manager Tempmodels with trails need their own unique
|
|
|
|
// number.
|
|
|
|
p->number = m_command_time_manager.AssignNumber();
|
|
|
|
p->cgd.flags |= T_ASSIGNED_NUMBER;
|
|
|
|
int oldnum = current_entity_number;
|
|
|
|
centity_t* oldcent = current_centity;
|
|
|
|
current_centity = NULL;
|
|
|
|
current_entity_number = p->number;
|
|
|
|
|
|
|
|
Event* swipeEv = new Event(EV_Client_SwipeOn);
|
|
|
|
swipeEv->AddString(p->cgd.swipe_shader);
|
|
|
|
swipeEv->AddString(p->cgd.swipe_tag_start);
|
|
|
|
swipeEv->AddString(p->cgd.swipe_tag_end);
|
|
|
|
swipeEv->AddFloat(p->cgd.swipe_life);
|
|
|
|
|
|
|
|
commandManager.ProcessEvent(swipeEv);
|
|
|
|
|
|
|
|
current_centity = oldcent;
|
|
|
|
current_entity_number = oldnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if this tiki has any emitters bound to it and update
|
|
|
|
// it's number. This is used for updating emitters that are attached to
|
|
|
|
// tempmodels.
|
|
|
|
if (p->cgd.tiki) {
|
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
spawnthing_t* st = m_emitters.ObjectAt(i);
|
|
|
|
|
|
|
|
if (st->cgd.tiki == p->cgd.tiki) {
|
|
|
|
// Assign this tempmodel a number if he doesn't already have
|
|
|
|
// one
|
|
|
|
if (p->number == -1) {
|
|
|
|
p->number = st->AssignNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
st->GetEmitTime(p->number);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
// Randomize avelocity or set absolute
|
|
|
|
p->cgd.avelocity[i] =
|
|
|
|
m_spawnthing->avelocity_amplitude[i] * random() +
|
|
|
|
m_spawnthing->avelocity_base[i];
|
|
|
|
|
|
|
|
// Randomize angles or set absolute
|
|
|
|
p->cgd.angles[i] += random() * m_spawnthing->angles_amplitude[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// If forward velocity is set, just use that otherwise use random
|
|
|
|
// variation of the velocity
|
|
|
|
if (m_spawnthing->forwardVelocity != 0) {
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
p->cgd.velocity[i] = newForward[i] *
|
|
|
|
m_spawnthing->forwardVelocity *
|
|
|
|
current_entity_scale;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p->cgd.flags2 & T2_PARALLEL) {
|
|
|
|
Vector v1 = p->cgd.origin - cg.refdef.vieworg;
|
|
|
|
vectoangles(v1, p->cgd.angles);
|
|
|
|
}
|
|
|
|
|
|
|
|
AnglesToAxis(p->cgd.angles, m_spawnthing->axis);
|
|
|
|
AxisCopy(m_spawnthing->axis, p->ent.axis);
|
|
|
|
|
|
|
|
// If align flag is set, adjust the angles to the direction of velocity
|
|
|
|
if (p->cgd.flags & (T_ALIGN | T_ALIGNONCE)) {
|
|
|
|
p->cgd.angles = p->cgd.velocity.toAngles();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Random offsets along axis
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (p->cgd.flags2 & T2_PARALLEL) {
|
|
|
|
p->cgd.origin +=
|
|
|
|
(Vector(m_spawnthing->axis[i]) *
|
|
|
|
m_spawnthing->axis_offset_amplitude[i] * random() +
|
|
|
|
m_spawnthing->axis_offset_base) *
|
|
|
|
current_entity_scale;
|
|
|
|
} else {
|
|
|
|
p->cgd.origin +=
|
|
|
|
(Vector(m_spawnthing->tag_axis[i]) *
|
|
|
|
m_spawnthing->axis_offset_amplitude[i] * random() +
|
|
|
|
m_spawnthing->axis_offset_base) *
|
|
|
|
current_entity_scale;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Calculate one tick of velocity based on time alive ( passed in )
|
|
|
|
p->cgd.origin =
|
|
|
|
p->cgd.origin + (p->cgd.velocity * ((float)p->aliveTime / 1000.0f) *
|
|
|
|
current_entity_scale);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (p->cgd.flags & T_AUTOCALCLIFE) {
|
|
|
|
Vector end, delta;
|
|
|
|
float length, speed;
|
|
|
|
vec3_t axis[3];
|
|
|
|
trace_t trace;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
AnglesToAxis(p->cgd.angles, axis);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
end = p->cgd.origin + Vector(axis[0]) * MAP_SIZE;
|
|
|
|
CG_Trace(&trace, p->cgd.origin, vec_zero, vec_zero, end,
|
|
|
|
ENTITYNUM_NONE, CONTENTS_SOLID | CONTENTS_WATER, qfalse,
|
|
|
|
qfalse, "AutoCalcLife");
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
delta = trace.endpos - p->cgd.origin;
|
|
|
|
length = delta.length();
|
|
|
|
speed = p->cgd.velocity.length();
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
p->cgd.life = (length / speed) * 1000.0f;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// global fading is based on the number of animations in the
|
|
|
|
// current_entity's animation
|
|
|
|
if (current_entity) {
|
|
|
|
if (m_spawnthing->cgd.flags & (T_GLOBALFADEIN | T_GLOBALFADEOUT)) {
|
|
|
|
int numframes = cgi.Anim_NumFrames(current_tiki,
|
|
|
|
current_entity->frameInfo[0].index);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
p->cgd.alpha = (float)current_entity->wasframe / (float)numframes;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (m_spawnthing->cgd.flags & T_GLOBALFADEOUT) {
|
|
|
|
p->cgd.alpha = 1.0f - p->cgd.alpha;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// EmitterOn
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EmitterOn(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
str name;
|
|
|
|
|
|
|
|
name = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
spawnthing_t* st = m_emitters.ObjectAt(i);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (st->emittername == name) {
|
|
|
|
emittertime_t* et;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
et = st->GetEmitTime(current_entity_number);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
et->active = qtrue;
|
|
|
|
et->last_emit_time = cg.time;
|
|
|
|
et->lerp_emitter = qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// EmitterOff
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::EmitterOff(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
str name;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
name = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
spawnthing_t* st = m_emitters.ObjectAt(i);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (st->emittername == name) {
|
|
|
|
emittertime_t* et;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
et = st->GetEmitTime(current_entity_number);
|
|
|
|
et->active = qfalse;
|
|
|
|
|
|
|
|
if (st->cgd.flags & T_BEAMTHING) {
|
|
|
|
// Kill any active beams emitted from this thing
|
|
|
|
CG_KillBeams(current_entity_number);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// Sound
|
|
|
|
//===============
|
2023-05-04 20:30:02 +02:00
|
|
|
void ClientGameCommandManager::PlaySound(str sound_name, vec3_t origin,
|
2023-04-30 20:20:58 +02:00
|
|
|
int channel, float volume,
|
|
|
|
float min_distance,
|
|
|
|
float pitch, int argstype)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-04 20:51:24 +02:00
|
|
|
int aliaschannel;
|
|
|
|
float aliasvolume;
|
|
|
|
float aliasmin_distance;
|
|
|
|
float aliaspitch;
|
2023-04-30 20:20:58 +02:00
|
|
|
const char* name = NULL;
|
2023-05-04 20:51:24 +02:00
|
|
|
static cvar_t* g_subtitle = cgi.Cvar_Get("g_subtitle", "0", CVAR_ARCHIVE);
|
|
|
|
static cvar_t* debugSound = cgi.Cvar_Get("debugSound", "0", 0);
|
|
|
|
float maxDist;
|
|
|
|
AliasListNode_t* soundAlias = NULL;
|
2023-04-30 20:20:58 +02:00
|
|
|
|
|
|
|
// FIXME
|
|
|
|
// TODO: Pitch modulation
|
|
|
|
// TODO: Alias enhancement
|
|
|
|
|
|
|
|
// Get the real sound to play
|
2023-05-02 20:13:48 +02:00
|
|
|
if (current_tiki && current_tiki->a->alias_list) {
|
2023-04-30 20:20:58 +02:00
|
|
|
name = cgi.Alias_ListFindRandom((AliasList_t*)current_tiki->a->alias_list,
|
|
|
|
sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!name) {
|
|
|
|
name = cgi.Alias_FindRandom(sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-04 20:51:24 +02:00
|
|
|
if (!name || !soundAlias) {
|
|
|
|
Com_Printf("\nERROR PlaySound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix.\n", sound_name.c_str());
|
|
|
|
return;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-04 20:51:24 +02:00
|
|
|
aliasvolume = soundAlias->volumeMod * random() + soundAlias->volume;
|
|
|
|
aliaspitch = soundAlias->pitchMod * random() + soundAlias->pitch;
|
|
|
|
aliasmin_distance = soundAlias->dist;
|
|
|
|
aliaschannel = soundAlias->channel;
|
|
|
|
maxDist = soundAlias->maxDist;
|
|
|
|
|
|
|
|
if (soundAlias->subtitle)
|
|
|
|
{
|
|
|
|
if (g_subtitle->integer
|
|
|
|
|| !sound_name.icmpn("den", 3)
|
|
|
|
|| !sound_name.icmpn("snd_den", 6))
|
|
|
|
{
|
|
|
|
// show subtitles if near the sound
|
|
|
|
if (origin
|
|
|
|
&& (g_subtitle->integer == 2 || DistanceSquared(origin, cg.refdef.vieworg) < (maxDist * maxDist)))
|
|
|
|
{
|
|
|
|
int curSub;
|
|
|
|
|
|
|
|
// also put subtitles if it's from a german dialogue
|
|
|
|
curSub = cgi.Cvar_Get("curSubtitle", "0", 0)->integer;
|
|
|
|
cgi.Cvar_Set(va("subtitle%d", curSub), va("%s", soundAlias->subtitle));
|
|
|
|
// increment the subtitle
|
|
|
|
cgi.Cvar_Set("curSubtitle", va("%d", (curSub + 1) % 4));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argstype)
|
|
|
|
{
|
|
|
|
if (argstype == 1)
|
|
|
|
{
|
|
|
|
if (debugSound->integer) {
|
|
|
|
Com_Printf("WARNING: Sound %s had its parm modified by code.\n", sound_name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (volume >= 0.0) {
|
|
|
|
volume = volume * aliasvolume;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
volume = aliasvolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pitch >= 0.0) {
|
|
|
|
pitch = pitch * aliaspitch;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pitch = aliaspitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (min_distance < 0.0) {
|
|
|
|
min_distance = aliasmin_distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel < 0) {
|
|
|
|
channel = aliaschannel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (debugSound->integer) {
|
|
|
|
Com_Printf("\nWARNING: OVERRIDE OVERRIDE OVERRIDESound %s had all its parm overriden by code.\n\n", sound_name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (volume < 0.0) {
|
|
|
|
volume = aliasvolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pitch < 0.0) {
|
|
|
|
pitch = aliaspitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (min_distance < 0.0) {
|
|
|
|
min_distance = aliasmin_distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel < 0) {
|
|
|
|
channel = aliaschannel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
volume = aliasvolume;
|
|
|
|
pitch = aliaspitch;
|
|
|
|
min_distance = aliasmin_distance;
|
|
|
|
channel = aliaschannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_entity_number == -1) {
|
|
|
|
cgi.S_StartSound(origin, ENTITYNUM_NONE, channel,
|
2023-04-30 20:20:58 +02:00
|
|
|
cgi.S_RegisterSound(name, soundAlias->streamed),
|
|
|
|
volume, min_distance, pitch, soundAlias->maxDist,
|
|
|
|
soundAlias->streamed);
|
2023-05-04 20:51:24 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
cgi.S_StartSound(origin, current_entity_number, channel,
|
|
|
|
cgi.S_RegisterSound(name, soundAlias->streamed),
|
|
|
|
volume, min_distance, pitch, soundAlias->maxDist,
|
|
|
|
soundAlias->streamed);
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// Sound
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::Sound(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int channel = CHAN_AUTO;
|
|
|
|
str sound_name;
|
|
|
|
float volume = -1.0;
|
|
|
|
float min_distance = -1.0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get all of the parameters
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
sound_name = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
channel = ev->GetInteger(2);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
volume = ev->GetFloat(3);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 3) {
|
|
|
|
min_distance = ev->GetFloat(4);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// play the sound
|
|
|
|
if (current_entity) {
|
2023-05-04 20:30:02 +02:00
|
|
|
PlaySound(sound_name, current_entity->origin, channel, volume,
|
2023-04-30 20:20:58 +02:00
|
|
|
min_distance);
|
|
|
|
} else {
|
|
|
|
PlaySound(sound_name, NULL, channel, volume, min_distance);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// StopSound
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::StopSound(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int channel;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
channel = ev->GetInteger(1);
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cgi.S_StopSound(current_entity_number, channel);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::StopAliasChannel(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
str sound_name;
|
|
|
|
const char* name;
|
|
|
|
AliasListNode_t* soundAlias;
|
|
|
|
|
2023-05-07 14:45:23 +02:00
|
|
|
name = NULL;
|
|
|
|
soundAlias = NULL;
|
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sound_name = ev->GetString(1);
|
|
|
|
if (current_tiki)
|
|
|
|
{
|
|
|
|
if (current_tiki->a->alias_list) {
|
|
|
|
name = cgi.Alias_ListFindRandom((AliasList_t*)current_tiki->a->alias_list, sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name) {
|
|
|
|
name = cgi.Alias_FindRandom(sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name || !soundAlias)
|
|
|
|
{
|
|
|
|
Com_Printf("\nERROR stopaliaschannel: couldn't find alias %s\n", sound_name.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cgi.S_StopSound(current_entity_number, soundAlias->channel);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// LoopSound
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::LoopSound(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str sound_name;
|
|
|
|
float volume = -1.0;
|
|
|
|
float min_dist = -1.0;
|
|
|
|
float max_dist = -1.0;
|
|
|
|
float pitch = 1.0;
|
|
|
|
const char* name = NULL;
|
|
|
|
AliasListNode_t* soundAlias = NULL;
|
|
|
|
|
|
|
|
if (!current_centity) {
|
|
|
|
cgi.DPrintf(
|
|
|
|
"CCM::LoopSound : LoopSound in %s without current_centity\n",
|
|
|
|
cgi.TIKI_Name(current_tiki));
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
sound_name = ev->GetString(1);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 1) {
|
|
|
|
volume = ev->GetFloat(2);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
min_dist = ev->GetFloat(3);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() > 3) {
|
|
|
|
max_dist = ev->GetFloat(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 4) {
|
|
|
|
pitch = ev->GetFloat(5);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Get the real sound to play
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (current_tiki) {
|
|
|
|
name = cgi.Alias_ListFindRandom((AliasList_t*)current_tiki->a->alias_list,
|
|
|
|
sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!name) {
|
|
|
|
name = cgi.Alias_FindRandom(sound_name.c_str(), &soundAlias);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!name) {
|
|
|
|
name = sound_name.c_str();
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
current_centity->tikiLoopSound = cgi.S_RegisterSound(name, qfalse);
|
|
|
|
current_centity->tikiLoopSoundVolume = volume;
|
|
|
|
current_centity->tikiLoopSoundMinDist = min_dist;
|
|
|
|
current_centity->tikiLoopSoundMaxDist = max_dist;
|
|
|
|
current_centity->tikiLoopSoundPitch = pitch;
|
|
|
|
current_centity->tikiLoopSoundFlags = 0;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// CacheResource
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void CacheResource(const char* stuff)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str real_stuff;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!stuff) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
real_stuff = stuff;
|
|
|
|
real_stuff.tolower();
|
|
|
|
|
|
|
|
if (strstr(real_stuff.c_str(), ".wav")) {
|
|
|
|
cgi.S_RegisterSound(real_stuff.c_str(), qfalse);
|
|
|
|
} else if (strstr(real_stuff.c_str(), ".mp3")) {
|
|
|
|
cgi.S_RegisterSound(real_stuff.c_str(), qfalse);
|
|
|
|
} else if (strstr(real_stuff.c_str(), ".tik")) {
|
|
|
|
cgi.R_RegisterServerModel(real_stuff.c_str());
|
|
|
|
} else if (strstr(real_stuff.c_str(), ".spr")) {
|
|
|
|
cgi.R_RegisterShader(real_stuff.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===============
|
|
|
|
// Cache
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::Cache(Event* ev)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CacheResource(ev->GetString(1));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::CacheImage(Event* ev)
|
|
|
|
{
|
|
|
|
// FIXME: stub
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::CacheFont(Event* ev)
|
|
|
|
{
|
|
|
|
// FIXME: stub
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// AliasResource
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void AliasResource(dtiki_t* pmdl, const char* alias, const char* realname,
|
|
|
|
const char* parameters)
|
|
|
|
{
|
|
|
|
if (pmdl) {
|
|
|
|
if (!pmdl->a->alias_list) {
|
|
|
|
pmdl->a->alias_list = cgi.AliasList_New(pmdl->a->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
cgi.Alias_ListAdd((AliasList_t*)pmdl->a->alias_list, alias, realname, parameters);
|
|
|
|
} else {
|
|
|
|
cgi.Alias_Add(alias, realname, parameters);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
int bLoadForMap__FPCcT0(char* psMapsBuffer, char* name)
|
|
|
|
{
|
|
|
|
// FIXME: stub
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// AliasCache
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::AliasCache(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char parmbuffer[512]; // this holds the parameters to be passed into the
|
|
|
|
// alias command
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// alias is in argument 1
|
|
|
|
// real path is argument 2
|
|
|
|
// any additional parameters are in arguments 3-n
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
parmbuffer[0] = 0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 3; i <= ev->NumArgs(); i++) {
|
|
|
|
strcat(parmbuffer, ev->GetToken(i));
|
|
|
|
strcat(parmbuffer, " ");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
|
|
|
CacheResource(ev->GetString(2));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// Alias
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::Alias(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char parmbuffer[512]; // this holds the parameters to be passed into the
|
|
|
|
// alias command
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (ev->NumArgs() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// alias is in argument 1
|
|
|
|
// real path is argument 2
|
|
|
|
// any additional parameters are in arguments 3-n
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
parmbuffer[0] = 0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
for (i = 3; i <= ev->NumArgs(); i++) {
|
|
|
|
strcat(parmbuffer, ev->GetToken(i));
|
|
|
|
strcat(parmbuffer, " ");
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
void CacheAliasList(AliasList_t* alias_list, str& name)
|
2023-05-05 22:58:34 +02:00
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!alias_list) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int iFirst, iLast;
|
|
|
|
float fTotalWeight;
|
|
|
|
|
|
|
|
cgi.Alias_ListFindRandomRange((AliasList_t*)alias_list, name.c_str(), &iFirst, &iLast, &fTotalWeight);
|
|
|
|
if (iFirst >= 0 && iLast >= iFirst)
|
|
|
|
{
|
|
|
|
for (i = iFirst; i <= iLast; ++i) {
|
|
|
|
CacheResource(alias_list->sorted_list[i]->real_name);
|
|
|
|
}
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::CacheAlias(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
str name = ev->GetString(1);
|
|
|
|
|
|
|
|
if (current_tiki) {
|
|
|
|
CacheAliasList((AliasList_t*)current_tiki->a->alias_list, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
CacheAliasList(cgi.Alias_GetGlobalList(), name);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// Footstep
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::Footstep(Event* ev)
|
|
|
|
{
|
2023-05-06 17:02:40 +02:00
|
|
|
int iRunning, iEquipment;
|
|
|
|
str sTagName;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-06 17:02:40 +02:00
|
|
|
sTagName = ev->GetString(1);
|
|
|
|
|
|
|
|
iRunning = 1;
|
|
|
|
if (ev->NumArgs() > 1)
|
|
|
|
{
|
|
|
|
str sType = ev->GetString(2);
|
|
|
|
if (!str::icmp(sType, "walk"))
|
|
|
|
{
|
|
|
|
// walking
|
|
|
|
iRunning = 0;
|
|
|
|
}
|
|
|
|
else if (!str::icmp(sType, "ladder"))
|
|
|
|
{
|
|
|
|
// on ladder
|
|
|
|
iRunning = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// running
|
|
|
|
iRunning = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
iEquipment = ev->GetInteger(3);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iEquipment = 1;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-01 19:22:05 +02:00
|
|
|
if (current_centity && current_entity) {
|
2023-05-06 17:02:40 +02:00
|
|
|
CG_Footstep(
|
|
|
|
sTagName.c_str(),
|
|
|
|
current_centity,
|
|
|
|
current_entity,
|
|
|
|
iRunning,
|
|
|
|
iEquipment
|
|
|
|
);
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::LandingSound(Event* ev)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int iEquipment;
|
|
|
|
float fVolume;
|
|
|
|
|
|
|
|
if (ev->NumArgs() <= 0) {
|
|
|
|
fVolume = 1.0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fVolume = ev->GetFloat(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() <= 1) {
|
|
|
|
iEquipment = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iEquipment = ev->GetInteger(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_centity && current_entity) {
|
|
|
|
CG_LandingSound(current_centity, current_entity, fVolume, iEquipment);
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-05-05 23:43:27 +02:00
|
|
|
void ClientGameCommandManager::BodyFallSound(Event* ev)
|
2023-05-05 22:58:34 +02:00
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
float fVolume;
|
|
|
|
|
|
|
|
if (ev->NumArgs() <= 0) {
|
|
|
|
fVolume = 1.0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fVolume = ev->GetFloat(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_centity && current_entity) {
|
|
|
|
CG_BodyFallSound(current_centity, current_entity, fVolume);
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//===============
|
|
|
|
// Client
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::Client(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
Event* event;
|
|
|
|
const char* eventname;
|
|
|
|
int i;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// see if it was a dummy command
|
|
|
|
if (ev->NumArgs() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
eventname = ev->GetString(1);
|
|
|
|
event = new Event(eventname);
|
|
|
|
|
|
|
|
for (i = 2; i <= ev->NumArgs(); i++) {
|
|
|
|
event->AddToken(ev->GetToken(i));
|
|
|
|
}
|
|
|
|
ProcessEvent(event);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// TagDynamicLight
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::TagDynamicLight(Event* ev)
|
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
int tagnum;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Spawn a single tempmodel that is a dynamic light
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
|
|
|
|
|
|
|
tagname = ev->GetString(1);
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist", tagname.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
GetOrientation(tagnum, m_spawnthing);
|
|
|
|
|
|
|
|
m_spawnthing->cgd.flags |= T_DLIGHT;
|
|
|
|
m_spawnthing->cgd.color[0] = ev->GetFloat(2) * 255;
|
|
|
|
m_spawnthing->cgd.color[1] = ev->GetFloat(3) * 255;
|
|
|
|
m_spawnthing->cgd.color[2] = ev->GetFloat(4) * 255;
|
|
|
|
m_spawnthing->cgd.color[3] = 255;
|
|
|
|
m_spawnthing->cgd.lightIntensity = ev->GetFloat(5);
|
|
|
|
m_spawnthing->cgd.life = ev->GetFloat(6) * 1000;
|
|
|
|
if (ev->NumArgs() > 6) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(7));
|
|
|
|
if (ev->NumArgs() > 7) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(8));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.lightType = 0;
|
|
|
|
}
|
|
|
|
SpawnTempModel(1, m_spawnthing);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===============
|
|
|
|
// OriginDynamicLight
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::OriginDynamicLight(Event* ev)
|
|
|
|
|
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
|
|
|
|
if (!current_entity) {
|
|
|
|
cgi.DPrintf("ClientGameCommandManager::OriginDynamicLight : Illegal "
|
|
|
|
"use of \"origindlight\"\n");
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Spawn a single tempmodel that is a dynamic light
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
|
|
|
|
|
|
|
m_spawnthing->cgd.origin = current_entity->origin;
|
|
|
|
m_spawnthing->cgd.flags |= T_DLIGHT;
|
|
|
|
m_spawnthing->cgd.color[0] = ev->GetFloat(1) * 255;
|
|
|
|
m_spawnthing->cgd.color[1] = ev->GetFloat(2) * 255;
|
|
|
|
m_spawnthing->cgd.color[2] = ev->GetFloat(3) * 255;
|
|
|
|
m_spawnthing->cgd.color[3] = 255;
|
|
|
|
m_spawnthing->cgd.lightIntensity = ev->GetFloat(4);
|
|
|
|
m_spawnthing->cgd.life = ev->GetFloat(5) * 1000;
|
|
|
|
if (ev->NumArgs() > 5) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(6));
|
|
|
|
if (ev->NumArgs() > 6) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(7));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.lightType = 0;
|
|
|
|
}
|
|
|
|
SpawnTempModel(1, m_spawnthing);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//===============
|
|
|
|
// DynamicLight
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::DynamicLight(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str tagname;
|
|
|
|
|
|
|
|
// The emitter itself has a dynamic light
|
|
|
|
m_spawnthing->cgd.flags |= T_DLIGHT;
|
|
|
|
m_spawnthing->dcolor[0] = ev->GetFloat(1);
|
|
|
|
m_spawnthing->dcolor[1] = ev->GetFloat(2);
|
|
|
|
m_spawnthing->dcolor[2] = ev->GetFloat(3);
|
|
|
|
m_spawnthing->cgd.lightIntensity = ev->GetFloat(4);
|
|
|
|
if (ev->NumArgs() > 4) {
|
|
|
|
m_spawnthing->cgd.lightType |= (dlighttype_t)ev->GetInteger(5);
|
|
|
|
if (ev->NumArgs() > 5) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(6));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_spawnthing->cgd.lightType = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::BlockDynamicLight(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!current_entity)
|
|
|
|
{
|
|
|
|
m_spawnthing = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
endblockfcn = &ClientGameCommandManager::EndBlockDynamicLight;
|
|
|
|
|
|
|
|
if (!m_pCurrentSfx) {
|
|
|
|
m_spawnthing = &m_localemitter;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitializeSpawnthing(m_spawnthing);
|
|
|
|
m_spawnthing->cgd.origin = current_entity->origin;
|
|
|
|
m_spawnthing->cgd.flags |= T_DLIGHT;
|
|
|
|
m_spawnthing->cgd.lightIntensity = ev->GetFloat(1);
|
|
|
|
m_spawnthing->cgd.life = ev->GetFloat(2);
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(3));
|
|
|
|
if (ev->NumArgs() > 3) {
|
|
|
|
m_spawnthing->cgd.lightType |= DLightNameToNum(ev->GetString(4));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_spawnthing->cgd.lightType = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->axis);
|
|
|
|
AxisCopy(current_entity->axis, m_spawnthing->tag_axis);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-05-06 23:37:05 +02:00
|
|
|
void ClientGameCommandManager::EndBlockDynamicLight()
|
2023-05-05 22:58:34 +02:00
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
if (!m_spawnthing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpawnEffect(m_spawnthing->count, 0);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
static int emittercount = 0;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// UpdateBeam
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::UpdateBeam(dtiki_t* tiki, int entity_number,
|
|
|
|
spawnthing_t* beamthing)
|
|
|
|
{
|
|
|
|
Vector start, end;
|
|
|
|
int renderfx;
|
|
|
|
qboolean addstartpoint;
|
|
|
|
float scale, alpha;
|
|
|
|
emittertime_t* et;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
et = beamthing->GetEmitTime(entity_number);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!et->active) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (current_entity) {
|
|
|
|
renderfx = (current_entity->renderfx &
|
|
|
|
~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
|
|
|
|
scale = current_entity->scale;
|
|
|
|
alpha = (float)current_entity->shaderRGBA[3] / 255.0f;
|
|
|
|
} else {
|
|
|
|
renderfx = 0;
|
|
|
|
scale = 1.0f;
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (beamthing->startTag == "USE_TAGLIST") {
|
|
|
|
int i, count;
|
|
|
|
str startTag, endTag;
|
|
|
|
int tagnum;
|
|
|
|
Vector dir;
|
|
|
|
|
|
|
|
count = beamthing->m_taglist.NumObjects();
|
|
|
|
|
|
|
|
if (!count) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
startTag = beamthing->m_taglist.ObjectAt(1);
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, startTag.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist",
|
|
|
|
startTag.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
GetOrientation(tagnum, beamthing);
|
|
|
|
start = beamthing->cgd.origin;
|
|
|
|
if (beamthing->beamflags & BEAM_OFFSET_ENDPOINTS) {
|
|
|
|
dir = Vector(crandom(), crandom(), crandom());
|
|
|
|
start += (crandom() * beamthing->min_offset * dir) +
|
|
|
|
(crandom() * beamthing->max_offset * dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_MultiBeamBegin();
|
|
|
|
addstartpoint = qtrue;
|
|
|
|
|
|
|
|
for (i = 2; i <= count; i++) {
|
|
|
|
str s;
|
|
|
|
|
|
|
|
s = va("%d", i);
|
|
|
|
|
|
|
|
endTag = beamthing->m_taglist.ObjectAt(i);
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, endTag.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist",
|
|
|
|
endTag.c_str());
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
GetOrientation(tagnum, beamthing);
|
|
|
|
end = beamthing->cgd.origin;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (beamthing->beamflags & BEAM_OFFSET_ENDPOINTS) {
|
|
|
|
dir = Vector(crandom(), crandom(), crandom());
|
|
|
|
end += (crandom() * beamthing->min_offset * dir) +
|
|
|
|
(crandom() * beamthing->max_offset * dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_MultiBeamAddPoints(start, end, beamthing->numSubdivisions,
|
|
|
|
beamthing->beamflags, beamthing->min_offset,
|
|
|
|
beamthing->max_offset, addstartpoint);
|
|
|
|
|
|
|
|
addstartpoint = qfalse;
|
|
|
|
startTag = endTag;
|
|
|
|
start = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte newcolor[4];
|
|
|
|
|
|
|
|
newcolor[0] = beamthing->cgd.color[0] * alpha;
|
|
|
|
newcolor[1] = beamthing->cgd.color[1] * alpha;
|
|
|
|
newcolor[2] = beamthing->cgd.color[2] * alpha;
|
|
|
|
newcolor[3] = beamthing->cgd.color[3] * alpha;
|
|
|
|
|
|
|
|
CG_MultiBeamEnd(
|
|
|
|
beamthing->cgd.scale * scale, renderfx, beamthing->cgd.shadername,
|
|
|
|
newcolor, beamthing->beamflags, entity_number, beamthing->cgd.life);
|
|
|
|
} else {
|
|
|
|
if (beamthing->startTag.length()) {
|
|
|
|
int tagnum = cgi.Tag_NumForName(current_tiki, beamthing->startTag.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist",
|
|
|
|
beamthing->startTag.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use a dummy sp to get the orientation
|
|
|
|
GetOrientation(tagnum, beamthing);
|
|
|
|
start = beamthing->cgd.origin;
|
|
|
|
} else {
|
|
|
|
start = beamthing->cgd.origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (beamthing->endTag.length()) {
|
|
|
|
int tagnum = cgi.Tag_NumForName(current_tiki, beamthing->endTag.c_str());
|
|
|
|
if (tagnum == -1) {
|
|
|
|
throw ScriptException("Tagname '%s' does not exist",
|
|
|
|
beamthing->endTag.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use a dummy sp to get the orientation
|
|
|
|
GetOrientation(tagnum, beamthing);
|
|
|
|
end = beamthing->cgd.origin;
|
|
|
|
} else {
|
|
|
|
end = start + Vector(beamthing->axis[0]) * beamthing->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_CreateBeam(start, vec_zero, entity_number, 1,
|
|
|
|
beamthing->cgd.alpha * alpha,
|
|
|
|
beamthing->cgd.scale * scale,
|
|
|
|
(beamthing->beamflags | BEAM_LIGHTNING_EFFECT),
|
|
|
|
beamthing->length, beamthing->cgd.life, qfalse, end,
|
|
|
|
beamthing->min_offset, beamthing->max_offset,
|
|
|
|
beamthing->overlap, beamthing->numSubdivisions,
|
|
|
|
beamthing->delay, beamthing->cgd.shadername,
|
|
|
|
beamthing->cgd.color, beamthing->numspherebeams,
|
|
|
|
beamthing->sphereRadius, beamthing->toggledelay,
|
|
|
|
beamthing->endalpha, renderfx, beamthing->emittername);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===============
|
|
|
|
// UpdateEmitter
|
|
|
|
//===============
|
|
|
|
void ClientGameCommandManager::UpdateEmitter(dtiki_t* tiki, vec3_t axis[3],
|
|
|
|
int entity_number,
|
|
|
|
int parent_number,
|
|
|
|
Vector entity_origin)
|
|
|
|
|
|
|
|
{
|
|
|
|
int parent, lastparent, i;
|
|
|
|
emittertime_t* et = NULL;
|
|
|
|
centity_t* pc;
|
|
|
|
int count = 0;
|
|
|
|
float scale = 1.0f;
|
|
|
|
|
|
|
|
if (current_entity) {
|
|
|
|
scale = current_entity->scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the emitter associated with this model
|
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
m_spawnthing = m_emitters.ObjectAt(i);
|
|
|
|
|
|
|
|
if (m_spawnthing->cgd.tiki != tiki) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
et = m_spawnthing->GetEmitTime(entity_number);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!et->active) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((m_spawnthing->cgd.flags & T_DETAIL) && !cg_detail->integer) {
|
|
|
|
et->last_emit_time = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the default origin (spawn from the parent's origin)
|
|
|
|
VectorCopy(entity_origin, m_spawnthing->cgd.origin);
|
|
|
|
|
|
|
|
if (m_spawnthing->cgd.flags & T_BEAMTHING) {
|
|
|
|
if (m_spawnthing->cgd.flags & T_ANGLES) {
|
|
|
|
vec3_t axis[3];
|
|
|
|
|
|
|
|
AnglesToAxis(m_spawnthing->cgd.angles, axis);
|
|
|
|
AxisCopy(axis, m_spawnthing->axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateBeam(tiki, entity_number, m_spawnthing);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (m_spawnthing->tagnum == -1) {
|
|
|
|
// Set the axis and origin based on the tag's axis and origin
|
|
|
|
GetOrientation(m_spawnthing->tagnum, m_spawnthing);
|
|
|
|
} else if (axis) {
|
|
|
|
// Set the axis based on the entity's axis.
|
|
|
|
AxisCopy(axis, m_spawnthing->axis);
|
|
|
|
} else {
|
|
|
|
AxisClear(m_spawnthing->axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are HARDLINKed then subtract off the parent's origin
|
|
|
|
if (m_spawnthing->cgd.flags & T_HARDLINK) {
|
|
|
|
m_spawnthing->cgd.parent = entity_number;
|
|
|
|
m_spawnthing->cgd.origin -= entity_origin;
|
|
|
|
} else if (m_spawnthing->cgd.flags & T_PARENTLINK) {
|
|
|
|
lastparent = ENTITYNUM_NONE;
|
|
|
|
|
|
|
|
parent = parent_number;
|
|
|
|
|
|
|
|
// Find the topmost parent
|
|
|
|
while (parent != ENTITYNUM_NONE) {
|
|
|
|
pc = &cg_entities[parent];
|
|
|
|
lastparent = parent;
|
|
|
|
parent = pc->currentState.parent;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// The lastparent is the "real" parent
|
|
|
|
if (lastparent != ENTITYNUM_NONE) {
|
|
|
|
pc = &cg_entities[lastparent];
|
|
|
|
|
|
|
|
m_spawnthing->cgd.origin -= pc->lerpOrigin;
|
|
|
|
m_spawnthing->cgd.parent = lastparent;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
m_spawnthing->cgd.createTime = cg.time;
|
|
|
|
m_spawnthing->cgd.parentOrigin = Vector(entity_origin);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (m_spawnthing->cgd.flags & T_DLIGHT) {
|
|
|
|
cgi.R_AddLightToScene(
|
|
|
|
m_spawnthing->cgd.origin,
|
|
|
|
m_spawnthing->cgd.lightIntensity * scale,
|
|
|
|
m_spawnthing->dcolor[0], m_spawnthing->dcolor[1],
|
|
|
|
m_spawnthing->dcolor[2], m_spawnthing->cgd.lightType);
|
|
|
|
continue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
Vector save_origin = m_spawnthing->cgd.origin;
|
|
|
|
Vector delta = m_spawnthing->cgd.origin - et->oldorigin;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (m_spawnthing->spawnRate < 0) {
|
|
|
|
warning("ClientGameCommandManager::UpdateEmitter",
|
|
|
|
"Invalid spawnrate (negative)");
|
2023-04-30 00:02:16 +02:00
|
|
|
continue;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (paused->integer) {
|
|
|
|
et->last_emit_time = 0;
|
|
|
|
} else if ((et->last_emit_time > 0) && (m_spawnthing->spawnRate)) {
|
|
|
|
int dtime = cg.time - et->last_emit_time;
|
|
|
|
float lerp, lerpfrac;
|
|
|
|
|
|
|
|
if (et->last_emit_time > cg.time) {
|
|
|
|
et->last_emit_time = cg.time;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
|
|
|
|
count = dtime /
|
|
|
|
(m_spawnthing->spawnRate * (1.0f / cg_effectdetail->value));
|
|
|
|
|
|
|
|
// This is kind of a nasty bit of code. If the count is 1, just
|
|
|
|
// spawn a single tempmodel, if it's greater than 1, then spawn the
|
|
|
|
// number of tempmodels over a period of time, and adjust their
|
|
|
|
// create times accordingly. Also lerp the origins so they appear
|
|
|
|
// where they are supposed to. This helps smoothing out low frame
|
|
|
|
// rate situations where this is only get called a few times a
|
|
|
|
// second, but the spawn rate is high, and it will look a lot
|
|
|
|
// smoother.
|
|
|
|
if (!count) {
|
|
|
|
continue;
|
|
|
|
} else if (count == 1) {
|
|
|
|
SpawnTempModel(1);
|
|
|
|
et->last_emit_time = cg.time;
|
|
|
|
} else {
|
|
|
|
lerpfrac = 1.0f / (float)count;
|
|
|
|
|
|
|
|
lerp = 0;
|
|
|
|
while (dtime > (m_spawnthing->spawnRate *
|
|
|
|
(1.0f / cg_effectdetail->value))) {
|
|
|
|
et->last_emit_time = cg.time;
|
|
|
|
|
|
|
|
dtime -= m_spawnthing->spawnRate *
|
|
|
|
(1.0f / cg_effectdetail->value);
|
|
|
|
|
|
|
|
if (et->lerp_emitter) {
|
|
|
|
m_spawnthing->cgd.origin =
|
|
|
|
et->oldorigin + (delta * lerp);
|
|
|
|
}
|
|
|
|
|
|
|
|
SpawnTempModel(1, dtime);
|
|
|
|
|
|
|
|
lerp += lerpfrac;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
} else {
|
|
|
|
et->last_emit_time = cg.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_showemitters->integer) {
|
|
|
|
if (count) {
|
|
|
|
cgi.DPrintf("%d:%s:%d tempmodels emitted\n", entity_number,
|
|
|
|
m_spawnthing->emittername.c_str(), count);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Since we have an oldorigin, now we can do lerping
|
|
|
|
m_spawnthing->cgd.origin = save_origin;
|
|
|
|
et->oldorigin = save_origin;
|
|
|
|
et->lerp_emitter = qtrue;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// RemoveClientEntity - Removes an entity from being
|
|
|
|
// updated if it has emitters attached
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::RemoveClientEntity(int number, dtiki_t* tiki,
|
|
|
|
centity_t* cent,
|
|
|
|
ctempmodel_t* p)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Kill the emitters if they are attached to this tiki
|
|
|
|
if (number != -1) {
|
|
|
|
for (i = 1; i <= m_emitters.NumObjects(); i++) {
|
|
|
|
spawnthing_t* st = m_emitters.ObjectAt(i);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (st->cgd.tiki == tiki) {
|
|
|
|
st->RemoveEntity(number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn off any swiping for this entity number
|
|
|
|
int oldnum = current_entity_number;
|
|
|
|
centity_t* oldcent = current_centity;
|
|
|
|
|
|
|
|
current_centity = cent;
|
|
|
|
current_entity_number = number;
|
|
|
|
ProcessEvent(EV_Client_SwipeOff);
|
|
|
|
current_entity_number = oldnum;
|
|
|
|
current_centity = oldcent;
|
|
|
|
|
|
|
|
// If this tempmodel was assigned a temporary number then remove it from the
|
|
|
|
// command_time_manager
|
|
|
|
if (p && p->cgd.flags & T_ASSIGNED_NUMBER) {
|
|
|
|
m_command_time_manager.RemoveEntity(number);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
bool ClientGameCommandManager::GetTagPositionAndOrientation(int tagnum, orientation_t* new_or)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int i;
|
|
|
|
orientation_t tag_or;
|
|
|
|
|
|
|
|
if (!current_tiki || !current_entity) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
tag_or = cgi.TIKI_Orientation(current_entity, tagnum & TAG_MASK);
|
|
|
|
|
|
|
|
new_or->origin[0] = current_entity->origin[0];
|
|
|
|
new_or->origin[1] = current_entity->origin[1];
|
|
|
|
new_or->origin[2] = current_entity->origin[2];
|
|
|
|
|
|
|
|
for (i = 0; i < 3; ++i) {
|
|
|
|
VectorMA(new_or->origin, tag_or.origin[i], current_entity->axis[i], new_or->origin);
|
|
|
|
}
|
|
|
|
MatrixMultiply(tag_or.axis, current_entity->axis, new_or->axis);
|
|
|
|
|
|
|
|
return true;
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ClientGameCommandManager::GetTagPositionAndOrientation(str tagname, orientation_t* new_or)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int tagnum;
|
|
|
|
|
|
|
|
tagnum = cgi.Tag_NumForName(current_tiki, tagname.c_str());
|
|
|
|
if (tagnum < 0)
|
|
|
|
{
|
|
|
|
Class::warning(
|
|
|
|
"ClientGameCommandManager::GetTagPositionAndOrientation",
|
|
|
|
"Could not find tag \"%s\"",
|
|
|
|
tagname.c_str());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ClientGameCommandManager::GetTagPositionAndOrientation(tagnum, new_or);
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
|
|
|
// FreeAllTempModels
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::FreeAllTempModels(void)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
ctempmodel_t *p, *next;
|
|
|
|
|
|
|
|
// Go through all the temp models and run the physics if necessary,
|
|
|
|
// then add them to the ref
|
|
|
|
p = m_active_tempmodels.prev;
|
|
|
|
for (; p != &m_active_tempmodels; p = next) {
|
|
|
|
// grab next now, so if the local entity is freed we still have it
|
|
|
|
next = p->prev;
|
|
|
|
FreeTempModel(p);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
|
|
|
// FreeAllEmitters
|
|
|
|
//===============
|
2023-05-05 22:58:34 +02:00
|
|
|
void ClientGameCommandManager::RestartAllEmitters(void)
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-05 22:58:34 +02:00
|
|
|
// FIXME: stub??
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_RestartCommandManager
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-05-01 15:11:08 +02:00
|
|
|
void CG_RestartCommandManager()
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
commandManager.FreeAllTempModels();
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_ProcessInitCommands
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-05-01 00:10:07 +02:00
|
|
|
void CG_ProcessInitCommands(dtiki_t* tiki, refEntity_t* ent)
|
2023-04-30 14:47:18 +02:00
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int i, j;
|
|
|
|
int num_args;
|
|
|
|
refEntity_t* old_entity;
|
|
|
|
dtiki_t* old_tiki;
|
|
|
|
dtikicmd_t* pcmd;
|
|
|
|
|
|
|
|
if (!tiki) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old_entity = current_entity;
|
|
|
|
old_tiki = current_tiki;
|
|
|
|
current_entity = ent;
|
|
|
|
current_tiki = tiki;
|
|
|
|
|
|
|
|
for (i = 0; i < tiki->a->num_client_initcmds; i++)
|
|
|
|
{
|
|
|
|
Event* ev;
|
|
|
|
|
|
|
|
pcmd = &tiki->a->client_initcmds[i];
|
|
|
|
num_args = pcmd->num_args;
|
|
|
|
|
|
|
|
// Create the event and Process it.
|
|
|
|
ev = new Event(pcmd->args[0]);
|
|
|
|
|
|
|
|
for (j = 1; j < num_args; j++) {
|
|
|
|
ev->AddToken(pcmd->args[j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!commandManager.SelectProcessEvent(ev))
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n",
|
|
|
|
pcmd->args[0],
|
|
|
|
tiki->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity = old_entity;
|
|
|
|
current_tiki = old_tiki;
|
2023-05-01 00:10:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//=================
|
|
|
|
// CG_ProcessCacheInitCommands
|
|
|
|
//=================
|
|
|
|
void CG_ProcessCacheInitCommands(dtiki_t* tiki)
|
|
|
|
{
|
2023-05-06 17:27:25 +02:00
|
|
|
int i, j;
|
|
|
|
int num_args;
|
|
|
|
refEntity_t* old_entity;
|
|
|
|
dtiki_t* old_tiki;
|
|
|
|
dtikicmd_t* pcmd;
|
|
|
|
|
|
|
|
if (!tiki) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
old_entity = current_entity;
|
|
|
|
old_tiki = current_tiki;
|
|
|
|
current_entity = NULL;
|
|
|
|
current_tiki = tiki;
|
|
|
|
|
|
|
|
for (i = 0; i < tiki->a->num_client_initcmds; i++)
|
|
|
|
{
|
|
|
|
Event* ev;
|
|
|
|
|
|
|
|
pcmd = &tiki->a->client_initcmds[i];
|
|
|
|
num_args = pcmd->num_args;
|
|
|
|
|
|
|
|
// Create the event and Process it.
|
|
|
|
ev = new Event(pcmd->args[0]);
|
|
|
|
if (commandManager.GetFlags(ev) & EV_CACHE)
|
|
|
|
{
|
|
|
|
// only process even in which the cache flag is set
|
|
|
|
|
|
|
|
for (j = 1; j < num_args; j++) {
|
|
|
|
ev->AddToken(pcmd->args[j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!commandManager.SelectProcessEvent(ev))
|
|
|
|
{
|
|
|
|
Com_Printf(
|
|
|
|
"^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n",
|
|
|
|
pcmd->args[0],
|
|
|
|
tiki->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// no cache flags
|
|
|
|
delete ev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity = old_entity;
|
|
|
|
current_tiki = old_tiki;
|
2023-05-01 00:10:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CG_EndTiki(dtiki_t* tiki)
|
|
|
|
{
|
2023-05-01 15:11:08 +02:00
|
|
|
CG_DeleteEmitters(tiki);
|
2023-04-30 14:47:18 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_UpdateEntity
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_UpdateEntityEmitters(int entnum, refEntity_t* ent, centity_t* cent)
|
|
|
|
{
|
2023-04-30 01:42:57 +02:00
|
|
|
refEntity_t* old_entity = current_entity;
|
|
|
|
dtiki_t* old_tiki = current_tiki;
|
|
|
|
int oldnum = current_entity_number;
|
|
|
|
centity_t* oldcent = current_centity;
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// Check to see if this model has any emitters
|
|
|
|
current_entity = ent;
|
|
|
|
current_tiki = ent->tiki;
|
|
|
|
current_centity = cent;
|
|
|
|
current_entity_number = entnum;
|
|
|
|
|
|
|
|
if (cent->currentState.parent != ENTITYNUM_NONE) {
|
|
|
|
commandManager.UpdateEmitter(ent->tiki, ent->axis,
|
|
|
|
cent->currentState.number,
|
|
|
|
cent->currentState.parent, ent->origin);
|
|
|
|
} else {
|
|
|
|
commandManager.UpdateEmitter(
|
|
|
|
ent->tiki, ent->axis, cent->currentState.number,
|
|
|
|
cent->currentState.parent, cent->lerpOrigin);
|
|
|
|
}
|
|
|
|
current_entity = old_entity;
|
|
|
|
current_tiki = old_tiki;
|
|
|
|
current_centity = oldcent;
|
|
|
|
current_entity_number = oldnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void CG_AnimationDebugMessage(int number, const char* fmt, ...);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_ProcessEntityCommands
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-05-02 20:03:15 +02:00
|
|
|
qboolean CG_ProcessEntityCommands(int frame, int anim, int entnum, refEntity_t* ent, centity_t* cent)
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int num_args;
|
|
|
|
|
|
|
|
tiki_cmd_t tikicmds;
|
|
|
|
|
|
|
|
if (cgi.Frame_Commands(ent->tiki, anim, frame, &tikicmds)) {
|
|
|
|
current_entity = ent;
|
|
|
|
current_centity = cent;
|
|
|
|
current_entity_number = entnum;
|
|
|
|
current_tiki = ent->tiki;
|
|
|
|
CG_AnimationDebugMessage(
|
|
|
|
entnum,
|
|
|
|
"Processing Ent Commands: Entity: %3d Anim:#(%i) Frame:#(%i)\n",
|
|
|
|
anim, frame);
|
|
|
|
|
|
|
|
for (i = 0; i < tikicmds.num_cmds; i++) {
|
|
|
|
Event* ev;
|
|
|
|
|
|
|
|
num_args = tikicmds.cmds[i].num_args;
|
|
|
|
|
|
|
|
if (num_args > 0) {
|
|
|
|
// Create the event and Process it.
|
|
|
|
ev = new Event(tikicmds.cmds[i].args[0]);
|
|
|
|
|
|
|
|
for (j = 1; j < num_args; j++) {
|
|
|
|
ev->AddToken(tikicmds.cmds[i].args[j]);
|
|
|
|
}
|
|
|
|
|
2023-05-06 17:02:40 +02:00
|
|
|
commandManager.SelectProcessEvent(ev);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
current_tiki = NULL;
|
|
|
|
current_entity_number = -1;
|
|
|
|
current_entity = NULL;
|
|
|
|
current_centity = NULL;
|
|
|
|
}
|
2023-05-02 20:03:15 +02:00
|
|
|
|
|
|
|
return qtrue;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_ClientCommandDebugMessage
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_ClientCommandDebugMessage(centity_t* cent, const char* fmt, ...)
|
|
|
|
{
|
2023-04-30 00:02:16 +02:00
|
|
|
#ifndef NDEBUG
|
2023-04-30 20:20:58 +02:00
|
|
|
if (cg_debugAnim->integer) {
|
|
|
|
va_list argptr;
|
|
|
|
char msg[1024];
|
|
|
|
|
|
|
|
va_start(argptr, fmt);
|
|
|
|
vsprintf(msg, fmt, argptr);
|
|
|
|
va_end(argptr);
|
|
|
|
|
|
|
|
if ((!cg_debugAnimWatch->integer) ||
|
|
|
|
((cg_debugAnimWatch->integer - 1) == cent->currentState.number)) {
|
|
|
|
if (cg_debugAnim->integer == 2) {
|
|
|
|
cgi.DebugPrintf(msg);
|
|
|
|
} else {
|
|
|
|
cgi.Printf(msg);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_ClientCommands
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-05-02 20:03:15 +02:00
|
|
|
void CG_ClientCommands(refEntity_t* ent, centity_t* cent, int slot)
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
2023-05-02 20:03:15 +02:00
|
|
|
#if 0
|
2023-04-30 20:20:58 +02:00
|
|
|
int anim;
|
|
|
|
int frame;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!tiki) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (paused->integer) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (cent->currentState.eFlags & EF_DONT_PROCESS_COMMANDS) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
assert(cent);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// don't do anything if the frame is illegal
|
|
|
|
if ((new_frame < 0) || (new_frame >= state->numframes)) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
#ifndef NDEBUG
|
|
|
|
CG_ClientCommandDebugMessage(
|
|
|
|
cent,
|
|
|
|
"Client Commands: cg.time %d checking Entity %d anim %d frame %d\n",
|
|
|
|
cg.time,
|
|
|
|
cent->currentState.number,
|
|
|
|
new_anim,
|
|
|
|
new_frame
|
|
|
|
);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
anim = state->last_cmd_anim - 1;
|
|
|
|
frame = state->last_cmd_frame;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// if we had a last anim and it it wasn't same as ours then
|
|
|
|
// we need to run any exit commands from the last animation
|
|
|
|
if ((anim != new_anim) && (anim >= 0)) {
|
|
|
|
// play the exit command
|
|
|
|
CG_ProcessEntityCommands(TIKI_FRAME_EXIT, anim,
|
|
|
|
cent->currentState.number, ent, cent);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
CG_ClientCommandDebugMessage(
|
|
|
|
cent, "Client Commands: Entity %d Exiting Anim: %s\n",
|
|
|
|
cent->currentState.number, cgi.Anim_NameForNum(tiki, anim));
|
2023-04-30 00:02:16 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
frame = 0;
|
|
|
|
|
|
|
|
// Reset the tiki looping sound if changing animation
|
|
|
|
cent->tikiLoopSound = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state->has_commands) {
|
|
|
|
// if we are entering a new animation, than
|
|
|
|
// we need to run any entry commands for the new animation
|
|
|
|
if (anim != new_anim) {
|
|
|
|
// play the exit command
|
|
|
|
CG_ProcessEntityCommands(TIKI_FRAME_ENTRY, new_anim,
|
|
|
|
cent->currentState.number, ent, cent);
|
|
|
|
#ifndef NDEBUG
|
|
|
|
CG_ClientCommandDebugMessage(
|
|
|
|
cent, "Client Commands: Entity %d Entering Anim: %s\n",
|
|
|
|
cent->currentState.number,
|
|
|
|
cgi.Anim_NameForNum(tiki, new_anim));
|
2023-04-30 00:02:16 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (state->driven) {
|
|
|
|
// make sure we process this frame if we are on a new frame
|
|
|
|
// although this is a hack, it guarantees that the frame will be
|
|
|
|
// processed below.
|
|
|
|
frame %= state->numframes;
|
|
|
|
if (frame < new_frame) {
|
|
|
|
frame = new_frame;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// we need to catch up on the frames we haven't played yet
|
|
|
|
//
|
|
|
|
if ((new_frame != (frame - 1)) && (state->numframes > 1)) {
|
|
|
|
// and frame number so that it wraps properly
|
|
|
|
frame %= state->numframes;
|
|
|
|
|
|
|
|
// lerp to one minus the current frame
|
|
|
|
while (frame != new_frame) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
CG_ClientCommandDebugMessage(
|
|
|
|
cent,
|
|
|
|
"Client Commands: cg.time %d Catching up Entity: %d "
|
|
|
|
"Anim: %s frame: %d numframes: %d\n",
|
|
|
|
cg.time, cent->currentState.number,
|
|
|
|
cgi.Anim_NameForNum(tiki, new_anim), frame,
|
|
|
|
state->numframes);
|
2023-04-30 00:02:16 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
state->last_cmd_time =
|
|
|
|
cg.time + TIKI_FRAME_MAXFRAMERATE;
|
|
|
|
CG_ProcessEntityCommands(frame, new_anim,
|
|
|
|
cent->currentState.number, ent,
|
|
|
|
cent);
|
|
|
|
frame = (frame + 1) % state->numframes;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// handle the single frame and every frame case
|
|
|
|
//
|
|
|
|
if ((frame == new_frame) ||
|
|
|
|
((cg.time > state->last_cmd_time) &&
|
|
|
|
(cent->currentState.eFlags & EF_EVERYFRAME))) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
CG_ClientCommandDebugMessage(
|
|
|
|
cent,
|
|
|
|
"Client Commands: cg.time %d Processing Entity: %d Anim: %s "
|
|
|
|
"frame: %d numframes: %d\n",
|
|
|
|
cg.time, cent->currentState.number,
|
|
|
|
cgi.Anim_NameForNum(tiki, new_anim), new_frame,
|
|
|
|
state->numframes);
|
2023-04-30 00:02:16 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
state->last_cmd_time = cg.time + TIKI_FRAME_MAXFRAMERATE;
|
|
|
|
CG_ProcessEntityCommands(new_frame, new_anim,
|
|
|
|
cent->currentState.number, ent, cent);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (cent->clientFlags & CF_UPDATESWIPE) {
|
|
|
|
current_entity = ent;
|
|
|
|
current_centity = cent;
|
|
|
|
current_entity_number = cent->currentState.number;
|
|
|
|
current_tiki = tiki;
|
|
|
|
|
|
|
|
commandManager.ProcessEvent(EV_Client_Swipe);
|
|
|
|
|
|
|
|
current_tiki = NULL;
|
|
|
|
current_entity_number = -1;
|
|
|
|
current_entity = NULL;
|
|
|
|
current_centity = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
state->last_cmd_anim = new_anim + 1;
|
|
|
|
state->last_cmd_frame = new_frame + 1;
|
2023-05-02 20:03:15 +02:00
|
|
|
#endif
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_AddTempModels
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_AddTempModels(void) { commandManager.AddTempModels(); }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
//===============
|
|
|
|
// CG_InitializeCommandManager
|
|
|
|
//===============
|
|
|
|
void CG_InitializeCommandManager(void)
|
|
|
|
{
|
|
|
|
cg_showemitters = cgi.Cvar_Get("cg_showemitters", "0", 0);
|
2023-05-01 17:06:15 +02:00
|
|
|
commandManager.InitializeTempModelCvars();
|
|
|
|
commandManager.InitializeVSSCvars();
|
2023-04-30 20:20:58 +02:00
|
|
|
commandManager.InitializeTempModels();
|
2023-05-01 17:06:15 +02:00
|
|
|
commandManager.InitializeVSSSources();
|
2023-04-30 20:20:58 +02:00
|
|
|
commandManager.InitializeEmitters();
|
2023-05-01 17:06:15 +02:00
|
|
|
commandManager.InitializeRainCvars();
|
|
|
|
commandManager.InitializeBeams();
|
2023-04-30 20:20:58 +02:00
|
|
|
CG_InitTestEmitter();
|
2023-05-01 15:11:08 +02:00
|
|
|
CG_InitTestTreadMark();
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CG_ResetTempModels(void)
|
|
|
|
{
|
|
|
|
commandManager.ResetTempModels();
|
|
|
|
lastTempModelFrameTime = cg.time;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_RemoveClientEntity
|
2023-04-30 00:02:16 +02:00
|
|
|
//===============
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_RemoveClientEntity(int number, dtiki_t* tiki, centity_t* cent)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
commandManager.RemoveClientEntity(number, tiki, cent);
|
|
|
|
|
|
|
|
// Remove the beam list associated with this entity
|
|
|
|
RemoveBeamList(number);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//=================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_Command_ProcessFile
|
2023-04-30 00:02:16 +02:00
|
|
|
//=================
|
2023-05-01 00:10:07 +02:00
|
|
|
qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *curTiki)
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
char* buffer;
|
|
|
|
const char* bufstart;
|
|
|
|
char com_token[MAX_STRING_CHARS];
|
|
|
|
|
2023-04-30 23:30:14 +02:00
|
|
|
if (cgi.FS_ReadFile(filename, (void**)&buffer) == -1) {
|
2023-04-30 20:20:58 +02:00
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!quiet) {
|
|
|
|
cgi.DPrintf("CG_Command_ProcessFile: %s\n", filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
// we are not setting up for a tiki
|
|
|
|
current_tiki = NULL;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
bufstart = buffer;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
while (1) {
|
|
|
|
Event* ev;
|
|
|
|
|
|
|
|
// grab each line as we go
|
|
|
|
strcpy(com_token, COM_ParseExt(&buffer, qtrue));
|
|
|
|
if (!com_token[0]) {
|
2023-04-30 00:02:16 +02:00
|
|
|
break;
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmpi(com_token, "end") || !strcmpi(com_token, "server")) {
|
|
|
|
// skip the line
|
|
|
|
while (1) {
|
|
|
|
strcpy(com_token, COM_ParseExt(&buffer, qfalse));
|
|
|
|
if (!com_token[0]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the event
|
|
|
|
ev = new Event(com_token);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
// get the rest of the line
|
|
|
|
while (1) {
|
|
|
|
strcpy(com_token, COM_ParseExt(&buffer, qfalse));
|
|
|
|
if (!com_token[0]) {
|
|
|
|
break;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
ev->AddToken(com_token);
|
|
|
|
}
|
|
|
|
commandManager.ProcessEvent(ev);
|
|
|
|
}
|
|
|
|
cgi.FS_FreeFile((void*)bufstart);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
return qtrue;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
//===========================
|
2023-04-30 20:20:58 +02:00
|
|
|
// CG_ConsoleCommand Functions
|
2023-04-30 00:02:16 +02:00
|
|
|
//===========================
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_EventList_f(void)
|
|
|
|
{
|
|
|
|
const char* mask;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
mask = NULL;
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
mask = cgi.Argv(1);
|
|
|
|
}
|
|
|
|
Event::ListCommands(mask);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_EventHelp_f(void)
|
|
|
|
{
|
|
|
|
const char* mask;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
mask = NULL;
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
mask = cgi.Argv(1);
|
|
|
|
}
|
|
|
|
Event::ListDocumentation(mask);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_DumpEventHelp_f(void)
|
|
|
|
{
|
|
|
|
const char* mask;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
mask = NULL;
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
mask = cgi.Argv(1);
|
|
|
|
}
|
|
|
|
Event::ListDocumentation(mask, true);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_PendingEvents_f(void)
|
|
|
|
{
|
|
|
|
const char* mask;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
mask = NULL;
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
mask = cgi.Argv(1);
|
|
|
|
}
|
|
|
|
Event::PendingEvents(mask);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_ClassList_f(void) { listAllClasses(); }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_ClassTree_f(void)
|
|
|
|
{
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
listInheritanceOrder(cgi.Argv(1));
|
|
|
|
} else {
|
|
|
|
cgi.Printf("Syntax: cg_classtree [classname].\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_ClassEvents_f(void)
|
|
|
|
{
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
ClassEvents(cgi.Argv(1), qfalse);
|
|
|
|
} else {
|
|
|
|
Com_Printf("Syntax: cg_classevents [classname].\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_DumpClassEvents_f(void)
|
|
|
|
{
|
|
|
|
if (cgi.Argc() > 1) {
|
|
|
|
ClassEvents(cgi.Argv(1), qtrue);
|
|
|
|
} else {
|
|
|
|
Com_Printf("Syntax: cg_dumpclassevents [classname].\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_DumpAllClasses_f(void) { DumpAllClasses(); }
|
|
|
|
|
|
|
|
#define throw_assert assert(0), throw
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
EmitterLoader emitterLoader;
|
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
Event EV_EmitterLoader_Emitter("emitter", EV_DEFAULT, "s", "emittername",
|
|
|
|
"Create a new emitter");
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
CLASS_DECLARATION(Listener, EmitterLoader, NULL){
|
|
|
|
{&EV_EmitterLoader_Emitter, &EmitterLoader::Emitter},
|
|
|
|
{NULL, NULL }
|
|
|
|
};
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
EmitterLoader::EmitterLoader() { emitterActive = false; }
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void EmitterLoader::Emitter(Event* ev)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
spawnthing_t* st;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
st = commandManager.CreateNewEmitter(ev->GetString(1));
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (st) {
|
|
|
|
emitterActive = true;
|
|
|
|
commandManager.SetSpawnthing(st);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void EmitterLoader::ProcessEmitter(Script& script)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str token;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
while (script.TokenAvailable(true)) {
|
|
|
|
Event* ev = NULL;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
token = script.GetToken(true);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!str::cmp("}", token)) {
|
|
|
|
break;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
ev = new Event(token);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
while (script.TokenAvailable(false)) {
|
|
|
|
ev->AddToken(script.GetToken(false));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (emitterActive) {
|
|
|
|
commandManager.ProcessEvent(ev);
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
commandManager.SetSpawnthing(NULL);
|
|
|
|
emitterActive = NULL;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
bool EmitterLoader::Load(Script& script)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str token;
|
|
|
|
str errortext;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
try {
|
|
|
|
while (script.TokenAvailable(true)) {
|
|
|
|
Event* ev = NULL;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
token = script.GetToken(true);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!str::cmp("{", token)) {
|
|
|
|
ProcessEmitter(script);
|
|
|
|
} else if (!token.length() || !ValidEvent(token)) {
|
|
|
|
throw_assert "invalid token";
|
|
|
|
} else {
|
|
|
|
ev = new Event(token);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
while (script.TokenAvailable(false)) {
|
|
|
|
ev->AddToken(script.GetToken(false));
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
ProcessEvent(ev);
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
} catch (const char* s) {
|
|
|
|
cgi.DPrintf("emitter: error on line %d: %s\n", script.GetLineNumber(),
|
|
|
|
s);
|
|
|
|
return false;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void CG_Emitter(centity_t* cent)
|
|
|
|
{
|
|
|
|
spawnthing_t* emitter;
|
|
|
|
float dtime;
|
|
|
|
emittertime_t* et;
|
|
|
|
vec3_t mins, maxs;
|
|
|
|
|
|
|
|
emitter = commandManager.GetEmitterByName(
|
|
|
|
CG_ConfigString(CS_IMAGES + cent->currentState.tag_num));
|
|
|
|
|
|
|
|
if (emitter) {
|
|
|
|
vec3_t axis[3];
|
|
|
|
cgi.R_ModelBounds(cgs.inlineDrawModel[cent->currentState.modelindex],
|
|
|
|
mins, maxs);
|
|
|
|
|
|
|
|
emitter->cgd.origin[0] =
|
|
|
|
cent->lerpOrigin[0] + mins[0] + (random() * (maxs[0] - mins[0]));
|
|
|
|
emitter->cgd.origin[1] =
|
|
|
|
cent->lerpOrigin[1] + mins[1] + (random() * (maxs[1] - mins[1]));
|
|
|
|
emitter->cgd.origin[2] = cent->lerpOrigin[2] + maxs[2];
|
|
|
|
emitter->cgd.parentOrigin = Vector(cent->lerpOrigin);
|
|
|
|
emitter->cgd.parentOrigin[2] = cent->lerpOrigin[2] + maxs[2];
|
|
|
|
emitter->cgd.parentMins = mins;
|
|
|
|
emitter->cgd.parentMaxs = maxs;
|
|
|
|
|
|
|
|
AnglesToAxis(cent->lerpAngles, axis);
|
|
|
|
|
|
|
|
// Update the emitter time and spawn the tempmodels
|
|
|
|
et = emitter->GetEmitTime(cent->currentState.number);
|
|
|
|
|
|
|
|
if (et->last_emit_time > 0) {
|
|
|
|
dtime = cg.time - et->last_emit_time;
|
|
|
|
while (dtime > emitter->spawnRate) {
|
|
|
|
dtime -= emitter->spawnRate;
|
|
|
|
commandManager.SpawnTempModel(1, emitter);
|
|
|
|
et->last_emit_time = cg.time;
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-04-30 20:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
void ClientGameCommandManager::CGEvent(centity_t* cent)
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
{
|
|
|
|
str modelname;
|
|
|
|
dtiki_t *tiki;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
tiki = cgi.R_Model_GetHandle(cgs.model_draw[cent->currentState.modelindex]);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-04-30 20:20:58 +02:00
|
|
|
if (!tiki) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_EntityEffects(cent);
|
|
|
|
|
|
|
|
modelname = cgi.TIKI_Name(tiki);
|
|
|
|
m_spawnthing = InitializeSpawnthing(&m_localemitter);
|
|
|
|
|
|
|
|
AnglesToAxis(cent->lerpAngles, m_spawnthing->axis);
|
|
|
|
m_spawnthing->cgd.angles = cent->lerpAngles;
|
|
|
|
m_spawnthing->cgd.origin = cent->lerpOrigin;
|
|
|
|
m_spawnthing->cgd.scale = cent->currentState.scale;
|
|
|
|
m_spawnthing->cgd.alpha = cent->currentState.alpha;
|
|
|
|
|
|
|
|
m_spawnthing->cgd.color[0] = cent->color[0] * 255;
|
|
|
|
m_spawnthing->cgd.color[1] = cent->color[1] * 255;
|
|
|
|
m_spawnthing->cgd.color[2] = cent->color[2] * 255;
|
|
|
|
m_spawnthing->cgd.color[3] = cent->color[3] * 255;
|
|
|
|
|
|
|
|
Event* ev;
|
|
|
|
ev = new Event("model");
|
|
|
|
ev->AddString(modelname);
|
|
|
|
ProcessEvent(ev);
|
|
|
|
|
|
|
|
ev = new Event("anim");
|
|
|
|
ev->AddString("idle");
|
|
|
|
ProcessEvent(ev);
|
|
|
|
|
|
|
|
SpawnTempModel(1);
|
|
|
|
}
|
|
|
|
|
2023-05-01 15:49:45 +02:00
|
|
|
qboolean ClientGameCommandManager::SelectProcessEvent(Event* ev)
|
|
|
|
{
|
2023-05-06 17:02:40 +02:00
|
|
|
if (!m_fEventWait) {
|
|
|
|
return ProcessEvent(ev);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return PostEventForEntity(ev, m_fEventWait);
|
|
|
|
}
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::AddTreadMarkSources()
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::InitializeTreadMarkCvars()
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::InitializeTreadMarkSources()
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::ResetTreadMarkSources()
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::ResetTreadMarkSources(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-01 15:49:45 +02:00
|
|
|
}
|
|
|
|
|
2023-05-05 22:58:34 +02:00
|
|
|
void CG_Event(centity_t* cent)
|
|
|
|
{
|
|
|
|
commandManager.CGEvent(cent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SetCurrentTiki(Event* ev)
|
|
|
|
{
|
2023-05-06 21:10:36 +02:00
|
|
|
str tikiName;
|
|
|
|
|
|
|
|
if (ev->NumArgs() != 1)
|
|
|
|
{
|
|
|
|
Com_Printf("ERROR: settiki command takes 1 parameter.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tikiName = ev->GetString(1);
|
|
|
|
if (!str::icmp(tikiName.c_str(), "none")) {
|
|
|
|
current_tiki = cgi.TIKI_FindTiki(tikiName.c_str());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
current_tiki = NULL;
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::EventViewKick(Event* ev)
|
|
|
|
{
|
2023-05-06 16:15:28 +02:00
|
|
|
float vkmin[2], vkmax[2];
|
|
|
|
float fPitchMax, fYawMax, fScatterPitchMax;
|
|
|
|
str sPattern;
|
|
|
|
|
|
|
|
if (current_centity->currentState.parent != cg.snap->ps.clientNum) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 9) {
|
|
|
|
throw ScriptException("Wrong number of arguments for viewkick, should be 9\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
vkmin[0] = ev->GetFloat(1);
|
|
|
|
vkmax[0] = ev->GetFloat(2);
|
|
|
|
vkmin[1] = ev->GetFloat(3);
|
|
|
|
vkmax[1] = ev->GetFloat(4);
|
|
|
|
|
|
|
|
cg.viewkickRecenter = ev->GetFloat(5);
|
|
|
|
sPattern = ev->GetString(6);
|
|
|
|
|
|
|
|
fPitchMax = ev->GetFloat(7);
|
|
|
|
fYawMax = ev->GetFloat(8);
|
|
|
|
fScatterPitchMax = ev->GetFloat(9);
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 9) {
|
|
|
|
cg.viewkickMinDecay = ev->GetFloat(10);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cg.viewkickMinDecay = 12.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 10) {
|
|
|
|
cg.viewkickMaxDecay = ev->GetFloat(11);
|
|
|
|
}
|
|
|
|
else {
|
2023-05-06 17:50:41 +02:00
|
|
|
cg.viewkickMaxDecay = 25.0;
|
2023-05-06 16:15:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cg.viewkick[0] += vkmin[0] + random() * (vkmax[0] - vkmin[0]);
|
|
|
|
if (sPattern == "T")
|
|
|
|
{
|
|
|
|
cg.viewkick[1] += vkmin[1] + random() * (vkmax[1] - vkmin[1]);
|
|
|
|
}
|
|
|
|
else if (sPattern == "V")
|
|
|
|
{
|
|
|
|
cg.viewkick[1] += cg.viewkick[0] * (vkmin[1] + random() * (vkmax[1] - vkmin[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg.viewkick[0] < fScatterPitchMax)
|
|
|
|
{
|
|
|
|
if (cg.viewkick[0] <= -fScatterPitchMax)
|
|
|
|
{
|
|
|
|
cg.viewkick[0] += crandom() * 0.25;
|
|
|
|
cg.viewkick[1] += crandom() * 0.25;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cg.viewkick[0] -= crandom() * 0.25;
|
|
|
|
cg.viewkick[1] += crandom() * 3.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg.viewkick[0] > fPitchMax) {
|
|
|
|
cg.viewkick[0] = fPitchMax;
|
|
|
|
} else if (cg.viewkick[0] < -fPitchMax) {
|
|
|
|
cg.viewkick[0] = -fPitchMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg.viewkick[1] > fYawMax) {
|
|
|
|
cg.viewkick[1] = fYawMax;
|
|
|
|
}
|
|
|
|
else if (cg.viewkick[1] < -fYawMax) {
|
|
|
|
cg.viewkick[1] = -fYawMax;
|
|
|
|
}
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::SpawnTreads(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientGameCommandManager::TreadsOff(Event* ev)
|
|
|
|
{
|
2023-05-06 23:37:05 +02:00
|
|
|
// stub
|
2023-05-05 22:58:34 +02:00
|
|
|
}
|