Added custom GLSL with support for the new gl_fake16bit, gl_affinemodels

Added support for respawns of map entities
Started redoing hostages... they don't have any animations right now. Don't be surprised.
Moved most/if-not-all CS specific entities into their own class files
This commit is contained in:
Marco Cawthorne 2019-01-05 02:02:12 +01:00
parent 4f9e8c2a75
commit 4621358ffd
49 changed files with 1057 additions and 2904 deletions

View file

@ -1,116 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
ambient_generic
The ambient_generic allows you to play a specific sound.
Attributes:
Name (targetname) - Property used to identify entities.
WAV name (message) - This is the path/filename of the .wav file.
Volume (health) - Volume of the sound. Range: 0-10.
Dynamic Presets (preset) - Various effects that can be applied to the sound:
Flags:
Play Everywhere (1) - Sound will be heard in the entire level.
Small Radius (2) - Sound range is about 800 units at max volume.
Medium Radius (4) - Sound range is about 1250 units at max volume.
Large Radius (8) - Sound range is about 2000 units at max volume.
Start Silent (16) - Checking this means the entity must be triggered to work.
Not Toggled (32) - Older FGDs show this as Not Looped.
Makes the entity interpret each call as "turn on" instead of "toggle state".
Must be left unchecked for looping sound files.
Note that actual looping depends purely on cue points defined in the .wav file (see notes).
*/
void ambient_generic( void ) {
static float ambient_generic_send( entity ePEnt, float fChanged ) {
WriteByte( MSG_ENTITY, ENT_AMBIENTSOUND );
WriteCoord( MSG_ENTITY, self.origin_x );
WriteCoord( MSG_ENTITY, self.origin_y );
WriteCoord( MSG_ENTITY, self.origin_z );
WriteString( MSG_ENTITY, self.message );
WriteFloat( MSG_ENTITY, self.health );
WriteByte( MSG_ENTITY, self.style );
WriteByte( MSG_ENTITY, self.loop );
WriteByte( MSG_ENTITY, self.lforate );
return TRUE;
}
static void ambient_generic_use( void ) {
sound( self, CHAN_VOICE, self.message, self.health, self.style, self.pitch );
}
static void ambient_generic_useloop( void ) {
if ( self.state == TRUE ) {
self.message = "common/null.wav";
self.SendFlags = 128;
self.state = FALSE;
} else {
self.message = self.noise;
self.SendFlags = 128;
self.state = TRUE;
}
}
static void ambient_generic_respawn( void ) {
// If we are supposed to be looping, but have stopped playing... make sure we do again
if( !( self.spawnflags & 32 ) && ( self.state == FALSE ) ) {
ambient_generic_useloop();
}
}
precache_sound( self.message );
setorigin( self, self.origin );
self.health = self.health / 10;
if ( self.spawnflags & 1 ) {
self.style = ATTN_NONE;
} else if ( self.spawnflags & 2 ) {
self.style = ATTN_IDLE;
} else if ( self.spawnflags & 4 ) {
self.style = ATTN_STATIC;
} else if ( self.spawnflags & 8 ) {
self.style = ATTN_NORM;
} else {
self.style = ATTN_STATIC;
}
if ( self.spawnflags & 32 ) {
self.loop = FALSE;
} else {
self.loop = TRUE;
}
if( self.spawnflags & 16 ) {
self.vUse = ambient_generic_use;
} else {
self.noise = self.message; // Needed later for resuming
self.pvsflags = PVSF_NOREMOVE | PVSF_IGNOREPVS;
self.vUse = ambient_generic_useloop;
self.SendEntity = ambient_generic_send;
self.state = TRUE;
}
Entities_InitRespawnable( ambient_generic_respawn );
}

View file

@ -136,10 +136,6 @@ void TraceAttack_FireBullets( int iShots, vector vPos );
void Damage_Radius( vector vOrigin, entity eAttacker, float fDamage, float fRadius, int iCheckClip );
void Damage_Apply( entity eTarget, entity eAttacker, int iDamage, vector vHitPos, int iSkipArmor );
void Entities_UseTargets( void );
void Entities_InitRespawnable( void() vRespawnFunc );
void Entities_Respawn( void );
void Ammo_AutoFill(float fWeapon);
void Ammo_BuyPrimary(void);
void Ammo_BuySecondary(void);

View file

@ -24,11 +24,6 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
// GoldSrc-Rendermode Fields
.vector rendercolor;
.float rendermode;
.float renderamt;
.float alpha;
// All about +use
.void(void) vUse;
@ -78,24 +73,11 @@
/* Map Entity Specific Fields /*
* They used to be in their respective files, but there is not much point */
/* ambient_generic */
.float pitch;
.float loop;
.float lforate;
/* armoury_entity */
.float item;
.float count;
/* hostage_entity */
.entity eTargetPoint;
.entity eLastCreated;
.int iHasBeenUsed;
/* env_sprite */
.float framerate;
/* env_explosion */
.int iMagnitude;

View file

@ -6,57 +6,7 @@
*
****/
enum {
HOSTAGE_IDLE,
HOSTAGE_WALK,
HOSTAGE_RUN
};
enum {
HOSA_WALK,
HOSA_WALKSCARED,
HOSA_RUN,
HOSA_RUNSCARED,
HOSA_RUNLOOK,
HOSA_180LEFT,
HOSA_180RIGHT,
HOSA_FLINCH,
HOSA_PAIN,
HOSA_PAINLEFT,
HOSA_PAINRIGHT,
HOSA_PAINLEGLEFT,
HOSA_PAINLEGRIGHT,
HOSA_IDLE1,
HOSA_IDLE2,
HOSA_IDLE3,
HOSA_IDLE4,
HOSA_IDLE5,
HOSA_IDLE6,
HOSA_SCARED_END,
HOSA_SCARED1,
HOSA_SCARED2,
HOSA_SCARED3,
HOSA_SCARED4,
HOSA_PANIC,
HOSA_FEAR1,
HOSA_FEAR2,
HOSA_CRY,
HOSA_SCI1,
HOSA_SCI2,
HOSA_SCI3,
HOSA_DIE_SIMPLE,
HOSA_DIE_FORWARD1,
HOSA_DIE_FORWARD2,
HOSA_DIE_BACKWARD,
HOSA_DIE_HEADSHOT,
HOSA_DIE_GUTSHOT,
HOSA_LYING1,
HOSA_LYING2,
HOSA_DEADSIT,
HOSA_DEADTABLE1,
HOSA_DEADTABLE2,
HOSA_DEADTABLE3
};
/*
=================
@ -132,23 +82,7 @@ hostage_use
Whenever a hostage is 'used'
=================
*/
void hostage_use(void) {
if (eActivator.team == TEAM_CT) {
if ((self.eUser == world)) {
// Only give cash to the CT for using it for the first time
if (self.iHasBeenUsed == FALSE) {
Money_AddMoney(eActivator, 150);
sound(self, CHAN_VOICE, sprintf("hostage/hos%d.wav", random(1, 6)), 1.0, ATTN_IDLE);
self.iHasBeenUsed = TRUE;
}
self.eUser = eActivator;
self.eTargetPoint = self.eUser;
} else {
self.eUser = world;
}
}
}
/*
=================

View file

@ -1,275 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
====================
GOLDSRC-RENDERMODE STUFF
====================
*/
enum {
RENDERMODE_NORMAL = 0,
RENDERMODE_COLOR,
RENDERMODE_TEXTURE,
RENDERMODE_GLOW,
RENDERMODE_SOLID,
RENDERMODE_ADDITIVE
};
void Entities_RenderSetup( void ) {
// GoldSrc-Rendermode support
if ( self.rendermode != RENDERMODE_NORMAL ) {
self.alpha = ( self.renderamt / 255 );
self.colormod = self.rendercolor;
if( self.alpha == 0 ) {
self.alpha = 0.0001;
}
if ( self.rendermode == RENDERMODE_ADDITIVE ) {
self.effects = EF_ADDITIVE;
} else if ( self.rendermode == RENDERMODE_GLOW ) {
self.effects = EF_ADDITIVE | EF_FULLBRIGHT;
}
}
}
/*
====================
Entities_UseTargets
====================
*/
void Entities_UseTargets( void ) {
entity eFind = findchain( targetname, self.target );
entity eOld = self;
while ( eFind ) {
self = eFind;
dprint( sprintf( "Triggering %s %s\n", self.classname, self.targetname ) );
// Make sure we really do have a target...
if ( self.vUse != __NULL__ ) {
self.vUse();
}
eFind = eFind.chain;
}
self = eOld;
}
/*
====================
Entities_UseTargets_Delay
====================
*/
void Entities_UseTargets_Delay( float fDelay ) {
static void Entities_UseTargets_Delay_Think( void ) {
entity eOld = self;
self = self.owner;
Entities_UseTargets();
remove( eOld );
}
entity eTimer = spawn();
eTimer.owner = self;
eTimer.think = Entities_UseTargets_Delay_Think;
eTimer.nextthink = time + fDelay;
}
/*
====================
Entities_InitRespawnable
Called
====================
*/
void Entities_InitRespawnable( void() vRespawnFunc ) {
self.sOldModel = self.model;
self.fOldSolid = self.solid;
self.fOldHealth = self.health;
self.vOldOrigin = self.origin;
self.vOldAngle = self.angles;
self.vRespawn = vRespawnFunc;
self.vOldUse = self.vUse;
self.fRespawns = TRUE;
}
void Entities_Respawn( void ) {
self.model = self.sOldModel;
self.solid = self.fOldSolid;
self.health = self.fOldHealth;
self.origin = self.vOldOrigin;
self.angles = self.vOldAngle;
self.vUse = self.vOldUse;
Entities_RenderSetup();
self.vRespawn();
}
/*
====================
Entities_Remove
Technically, it doesn't remove everything
====================
*/
void Entities_Remove( void ) {
if ( self.fRespawns == TRUE ) {
setorigin( self, self.vOldOrigin );
self.solid = SOLID_NOT;
self.model = 0;
} else {
remove( self );
}
}
/*
====================
Entities_SetMovedir
Returns the movement direction based on angles
====================
*/
void Entities_SetMovementDirection( void )
{
if ( self.angles == '0 -1 0' ) {
self.movedir = '0 0 1';
} else if ( self.angles == '0 -2 0' ) {
self.movedir = '0 0 -1';
} else {
makevectors( self.angles );
self.movedir = v_forward;
}
self.angles = '0 0 0';
}
/*
====================
Entities_InitTrigger
Prepares an entity to have the properties of a TRIGGER
====================
*/
void Entities_InitTrigger( void ) {
if ( self.angles != '0 0 0' ) {
Entities_SetMovementDirection();
}
self.solid = SOLID_TRIGGER;
setmodel ( self, self.model );
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.model = "";
}
/*
====================
Entities_MoveToDestination_End
====================
*/
.vector vFinalDestination;
.void() vThinkMove;
void Entities_MoveToDestination_End( void ) {
setorigin( self, self.vFinalDestination );
self.velocity = '0 0 0';
self.nextthink = -1;
self.vThinkMove();
}
/*
====================
Entities_MoveToDestination
Sets velocity of an ent to move to a destination at the desired speed
====================
*/
void Entities_MoveToDestination(vector vDestination, float fMoveSpeed, void() func) {
local vector vPositionDifference;
local float fTravelLength, fTravelTime;
if ( !fMoveSpeed ) {
objerror("No speed defined for moving entity! Will not divide by zero.");
}
self.vThinkMove = func;
self.vFinalDestination = vDestination;
self.think = Entities_MoveToDestination_End;
if ( vDestination == self.origin ) {
self.velocity = '0 0 0';
self.nextthink = ( self.ltime + 0.1 );
return;
}
vPositionDifference = ( vDestination - self.origin );
fTravelLength = vlen( vPositionDifference );
fTravelTime = ( fTravelLength / fMoveSpeed );
if ( fTravelTime < 0.1 ) {
self.velocity = '0 0 0';
self.nextthink = self.ltime + 0.1;
return;
}
self.nextthink = ( self.ltime + fTravelTime );
self.velocity = ( vPositionDifference * ( 1 / fTravelTime ) );
}
/*
====================
Entities_CalcAngleMoveDone
====================
*/
.vector vFinalAngle;
void Entities_RotateToDestination_End( void ) {
self.angles = self.vFinalAngle;
self.avelocity = '0 0 0';
self.nextthink = -1;
self.vThinkMove();
}
/*
====================
Entities_RotateToDestination
Rotate to a given destination at a given pace
====================
*/
void Entities_RotateToDestination( vector vDestinationAngle, float fTravelSpeed, void() func ) {
local vector vAngleDifference;
local float fTravelLength, fTravelTime;
if ( !fTravelSpeed ) {
objerror("No speed defined for moving entity! Will not divide by zero.");
}
vAngleDifference = ( vDestinationAngle - self.angles );
fTravelLength = vlen( vAngleDifference );
fTravelTime = ( fTravelLength / fTravelSpeed );
self.nextthink = ( self.ltime + fTravelTime );
self.avelocity = ( vAngleDifference * ( 1 / fTravelTime ) );
self.vFinalAngle = vDestinationAngle;
self.vThinkMove = func;
self.think = Entities_RotateToDestination_End;
}

View file

@ -1,260 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
cycler_sprite
This entity lets you display and cycle through the animation of a sprite (or a model, engine doesn't care).
Attributes:
Name (targetname) - Property used to identify entities.
Pitch Yaw Roll (angles) - Sets the pitch (up / down), yaw (left / right) and roll (bank) respectively. The compass in WorldCraft / Hammer corresponds to Yaw. The settings are not always (or not all) used.
Sprite (model) - A sprite must be specified here (sprites/spritename.spr).
Frames per second (framerate) - Framerate the sprite will run at if animated.
=================
*/
void cycler_sprite( void ) {
static void cycler_sprite_respawn( void ) {
// Find something to do here...
}
precache_model( self.model );
setmodel( self, self.model );
Entities_RenderSetup();
Entities_InitRespawnable( cycler_sprite_respawn );
self.vUse = cycler_sprite_respawn;
}
void env_glow( void ) {
cycler_sprite();
}
/*
=================
env_sprite
This entity lets you display and cycle through the animation of a sprite.
Attributes:
Name (targetname) - Property used to identify entities.
Pitch Yaw Roll (angles) - Sets the pitch (up / down), yaw (left / right) and roll (bank) respectively. The compass in WorldCraft / Hammer corresponds to Yaw. The settings are not always (or not all) used.
Sprite (model) - A sprite must be specified here (sprites/spritename.spr).
Frames per second (framerate) - Framerate the sprite will run at if animated.
=================
*/
void env_sprite( void ) {
static float env_sprite_send( entity ePEnt, float fChanged ) {
WriteByte( MSG_ENTITY, ENT_SPRITE ); // Identifier
WriteCoord( MSG_ENTITY, self.origin_x );
WriteCoord( MSG_ENTITY, self.origin_y );
WriteCoord( MSG_ENTITY, self.origin_z );
WriteFloat( MSG_ENTITY, self.modelindex );
WriteFloat( MSG_ENTITY, self.framerate );
WriteFloat( MSG_ENTITY, self.scale );
WriteFloat( MSG_ENTITY, self.alpha );
WriteFloat( MSG_ENTITY, self.effects );
return TRUE;
}
static void env_sprite_use( void ) {
}
precache_model( self.model );
setmodel( self, self.model );
setorigin( self, self.origin );
Entities_RenderSetup();
self.pvsflags = PVSF_NOREMOVE | PVSF_IGNOREPVS;
self.SendEntity = env_sprite_send;
self.vUse = env_sprite_use;
}
/*
=================
env_render
This entity allows you to change the rendering properties
of most of the visible entities in the game (monsters, func_walls etc.), while the map is running.
The four render properties of the env_render will be copied to its target.
Attributes:
Name (targetname) - Property used to identify entities.
Target (target) - When an entity is activated, it triggers the entity with the name specified by Target.
Flags:
No Renderfx (1) - Render FX will not be copied.
No Renderamt (2) - Render Amount will not be copied.
No Rendermode (4) - Render Mode will not be copied.
No Rendercolor (8) - Render Color will not be copied.
Notes:
Use this entity to fake situations that would be impossible for the game engine,
such as apparently binding multiple entities together (e.g. a moving doorhandle on a rotating door).
With a bit of careful setup, it is possible to let the the doorhandle move first,
then become invisible, then let the door move (with a static doorhandle attached).
=================
*/
#define SF_NORENDERFX 1
#define SF_NORENDERAMT 2
#define SF_NORENDERMODE 4
#define SF_NORENDERCOLOR 8
void env_render( void ) {
static void env_render_use( void ) {
entity eFind = findchain( targetname, self.target );
while ( eFind ) {
if ( !( self.spawnflags & SF_NORENDERMODE ) ) {
eFind.rendermode = self.rendermode;
}
if ( !( self.spawnflags & SF_NORENDERCOLOR ) ) {
eFind.colormod = self.colormod;
}
eFind.alpha = self.alpha;
eFind = eFind.chain;
}
}
self.colormod = self.rendercolor;
Entities_RenderSetup();
self.vUse = env_render_use;
}
/*
=================
env_explosion
This entity creates any combination of fireball,
smoke, sparks, decals and sound, also known as an explosion.
Attributes:
Name (targetname) - Property used to identify entities.
Magnitude (iMagnitude) - The size of the explosion. 100 is average.
Flags:
No Damage (1) - Explosion won't cause any damage.
Repeatable (2) - Entity can be triggered more than once.
No Fireball (4) - There is no orange fireball. It won't look much like an explosion...
No Smoke (8) - Creates a pollution-free explosion.
No Decals (16) - No scorch marks are left behind.
No Sparks (32) - No sparks fly out.
Notes:
It's possible to create a similar effect with a combination of other entities,
but it wouldn't be much fun, so this quick and easy one is here instead!
=================
*/
enumflags {
ENVEXPLO_NODAMAGE,
ENVEXPLO_REPEATABLE,
ENVEXPLO_NOBALL,
ENVEXPLO_NOSMOKE,
ENVEXPLO_NODECAL,
ENVEXPLO_NOSPARKS
};
void env_explosion( void ) {
static void env_explosion_use( void ) {
Effect_CreateExplosion( self.origin );
if ( !( self.spawnflags & ENVEXPLO_NODAMAGE ) ) {
Damage_Radius( self.origin, self, 500, self.iMagnitude, TRUE );
}
if ( !( self.spawnflags & ENVEXPLO_REPEATABLE ) ) {
self.vUse = __NULL__;
remove( self );
}
}
self.vUse = env_explosion_use;
}
/*
=================
env_spark
Produces an electrical spark effect.
Attributes:
Name (targetname) - Property used to identify entities.
Pitch Yaw Roll (angles) - Sets the angles respectively.
Max Delay (MaxDelay) - Maximum delay between sparks.
Flags:
Toggle (32)
Start On (64)
Notes:
According to the fieldname MaxDelay, it is probably going to use
a random number to create a delay between the individual sparks.
I have no idea why they didn't just reuse the delay field.
We may never know.
=================
*/
#define SPARK_TOGGLE 32
#define SPARK_ON 64
void env_spark( void ) {
static void env_spark_fire( void ) {
Effect_CreateSpark( self.origin, self.angles );
}
static void env_spark_think( void ) {
env_spark_fire();
self.nextthink = time + ( random() * self.MaxDelay );
}
static void env_spark_use( void ) {
if ( self.spawnflags & SPARK_TOGGLE ) {
if ( self.think != __NULL__ ) {
self.think = __NULL__;
self.nextthink = 0;
} else {
self.think = env_spark_think;
self.nextthink = time + ( random() * self.MaxDelay );
}
} else {
env_spark_fire();
}
}
static void env_spark_respawn( void ) {
if ( self.MaxDelay <= 0 ) {
self.MaxDelay = 1.0f;
}
if ( self.spawnflags & SPARK_TOGGLE ) {
if ( self.spawnflags & SPARK_ON ) {
self.think = env_spark_think;
self.nextthink = time + ( random() * self.MaxDelay );
}
}
}
self.vUse = env_spark_use;
Entities_InitRespawnable( env_spark_respawn );
}

View file

@ -1,57 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_bomb_target_touch
Only for Ts, will give feedback whenever they are able to plant a bomb
=================
*/
void func_bomb_target_touch( void ) {
if ( iBombPlanted == TRUE ) {
return;
}
if ( ( other.classname == "player" ) && ( other.team == TEAM_T ) ) {
other.fInBombZone = TRUE; // Note: this will be cleared every frame inside SV_RunClientCommand
}
}
/*
=================
SPAWN: func_bomb_target
=================
*/
void func_bomb_target( void ) {
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
setmodel( self, self.model );
self.model = 0;
self.touch = func_bomb_target_touch;
iBombZones++;
}

View file

@ -1,172 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
// Entity information from http://twhl.info/wiki.php?id=164
/*
Flags
Only Trigger (1) - Entity can only be activated (broken) by being triggered.
Touch (2) - Brush will break on touch.
Pressure (4) - Brush will break when pressured (e.g. player walking on it).
*/
#define SF_TRIGGER 1
#define SF_TOUCH 2
#define SF_PRESSURE 4
/*
=================
func_breakable_pain
=================
*/
void func_breakable_pain( int iNull ) {
switch ( self.material ) {
case MATERIAL_GLASS:
case MATERIAL_COMPUTER:
case MATERIAL_GLASS_UNBREAKABLE:
sound( self, CHAN_VOICE, sprintf( "debris/glass%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_WOOD:
sound( self, CHAN_VOICE, sprintf( "debris/wood%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_METAL:
sound( self, CHAN_VOICE, sprintf( "debris/metal%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_FLESH:
float fRand = floor( random( 1, 8 ) );
if ( fRand == 4 ) { // sigh
fRand = 5;
}
sound( self, CHAN_VOICE, sprintf( "debris/flesh%d.wav", fRand ), 1.0, ATTN_NORM );
break;
case MATERIAL_CINDER:
case MATERIAL_ROCK:
sound( self, CHAN_VOICE, sprintf( "debris/concrete%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
}
}
/*
=================
func_breakable_die
=================
*/
void func_breakable_die( int iNull ) {
// Make sure this is dead
if ( self.vUse == __NULL__ ) {
return;
}
self.health = 0;
self.vUse = __NULL__;
Effect_BreakModel( self.absmin, self.absmax, self.velocity, self.material );
Entities_UseTargets();
Entities_Remove();
}
/*
=================
func_breakable_use
=================
*/
void func_breakable_use( void ) {
func_breakable_die( 0 );
}
/*
=================
func_breakable_touch
=================
*/
void func_breakable_touch( void ) {
static void func_breakable_touch_NULL( void ) { }
if( other.classname != "player" ) {
return;
}
if ( self.spawnflags & SF_TOUCH ) {
int fDamage = (float)(vlen( self.velocity ) * 0.01f );
if ( fDamage >= self.health ) {
self.touch = func_breakable_touch_NULL;
Damage_Apply( self, other, fDamage, self.absmin, FALSE );
if ( ( self.material == MATERIAL_GLASS ) || ( self.material == MATERIAL_COMPUTER ) ) {
Damage_Apply( other, self, fDamage / 4, other.origin, FALSE );
}
}
}
if ( ( self.spawnflags & SF_PRESSURE ) && ( other.absmin_z >= self.maxs_z - 2 ) ) {
self.think = func_breakable_use;
if ( self.delay == 0 ) {
self.delay = 0.1f;
}
self.nextthink = self.ltime + self.delay;
}
}
/*
=================
func_breakable_respawn
Respawns the breakable entity
=================
*/
void func_breakable_respawn( void ) {
if ( self.spawnflags & SF_TRIGGER ) {
self.takedamage = DAMAGE_NO;
} else {
self.takedamage = DAMAGE_YES;
self.vPain = func_breakable_pain;
self.vDeath = func_breakable_die;
self.iBleeds = FALSE;
}
if ( ( self.spawnflags & SF_TOUCH ) || ( self.spawnflags & SF_PRESSURE ) ) {
self.touch = func_breakable_touch;
}
self.vUse = func_breakable_use;
}
/*
=================
SPAWN: func_breakable
Entry function for the brushes that can die etc.
=================
*/
void func_breakable( void ) {
func_wall();
func_breakable_respawn();
Entities_InitRespawnable( func_breakable_respawn );
}

View file

@ -1,312 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#define SF_BTT_NOMOVE 1
#define SF_BTT_TOGGLE 32
#define SF_BTT_TOUCH_ONLY 256
void() FuncButton_MoveAway;
void() FuncButton_MoveBack;
void() FuncButton_Touch;
enum {
STATE_RAISED = 0,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
enum {
FRAME_OFF,
FRAME_ON
};
.float speed;
.float lip;
.float dmg;
.float state;
.vector pos1, pos2;
// Not all that customizable... but better than QUAKE.
.float movesnd;
.float stopsnd;
/*
====================
FuncButton_PrecacheSounds
====================
*/
void FuncButton_PrecacheSounds( void ) {
switch( self.sounds ) {
case 0:
// if you ever wondered why a silent button sounded a bit noisey... it's because this one kinda blows
self.noise = "common/null.wav";
break;
case 1:
self.noise = "buttons/button1.wav";
break;
case 2:
self.noise = "buttons/button2.wav";
break;
case 3:
self.noise = "buttons/button3.wav";
break;
case 4:
self.noise = "buttons/button4.wav";
break;
case 5:
self.noise = "buttons/button5.wav";
break;
case 6:
self.noise = "buttons/button6.wav";
break;
case 7:
self.noise = "buttons/button7.wav";
break;
case 8:
self.noise = "buttons/button8.wav";
break;
case 9:
self.noise = "buttons/button9.wav";
break;
case 10:
self.noise = "buttons/button10.wav";
break;
case 11:
self.noise = "buttons/button11.wav";
break;
case 12:
self.noise = "buttons/latchlocked1.wav";
break;
case 13:
self.noise = "buttons/latchunlocked1.wav";
break;
case 14:
self.noise = "buttons/lightswitch2.wav";
break;
case 21:
self.noise = "buttons/lever1.wav";
break;
case 22:
self.noise = "buttons/lever2.wav";
break;
case 23:
self.noise = "buttons/lever3.wav";
break;
case 24:
self.noise = "buttons/lever4.wav";
break;
case 25:
self.noise = "buttons/lever5.wav";
break;
default:
self.noise = "buttons/button9.wav";
}
precache_sound( self.noise );
}
/*
====================
FuncButton_Arrived
====================
*/
void FuncButton_Arrived( void ) {
self.state = STATE_RAISED;
if ( !( self.spawnflags & SF_BTT_TOUCH_ONLY ) ) {
self.touch = FuncButton_Touch;
}
if ( self.spawnflags & SF_BTT_TOGGLE ) {
return;
}
if ( self.wait != -1 ) {
self.think = FuncButton_MoveBack;
self.nextthink = ( self.ltime + self.wait );
}
}
/*
====================
FuncButton_Returned
====================
*/
void FuncButton_Returned( void ) {
if ( !( self.spawnflags & SF_BTT_TOUCH_ONLY ) ) {
self.touch = FuncButton_Touch;
}
self.state = STATE_LOWERED;
self.frame = FRAME_OFF;
}
/*
====================
FuncButton_MoveBack
====================
*/
void FuncButton_MoveBack( void ) {
if ( !( self.spawnflags & SF_BTT_TOUCH_ONLY ) ) {
self.touch = __NULL__;
}
self.state = STATE_DOWN;
if ( self.pos2 != self.pos1 ) {
Entities_MoveToDestination ( self.pos1, self.speed, FuncButton_Returned );
} else {
FuncButton_Returned();
}
}
/*
====================
FuncButton_MoveAway
====================
*/
void FuncButton_MoveAway( void ) {
if ( self.state == STATE_UP ) {
return;
}
if ( self.state == STATE_RAISED ) {
self.nextthink = ( self.ltime + self.wait );
return;
}
self.state = STATE_UP;
if ( self.pos2 != self.pos1 ) {
Entities_MoveToDestination ( self.pos2, self.speed, FuncButton_Arrived );
} else {
FuncButton_Arrived();
}
self.frame = FRAME_ON;
}
/*
====================
FuncButton_Trigger
====================
*/
void FuncButton_Trigger( void ) {
if ( self.fAttackFinished > time ) {
return;
}
self.fAttackFinished = time + self.wait;
if ( ( self.state == STATE_UP ) || ( self.state == STATE_RAISED ) ){
if ( self.wait != -1 ) {
FuncButton_MoveBack();
}
return;
}
sound( self, CHAN_VOICE, self.noise, 1.0, ATTN_NORM );
FuncButton_MoveAway();
if ( self.delay ) {
Entities_UseTargets_Delay( self.delay );
} else {
Entities_UseTargets();
}
}
/*
====================
FuncButton_Touch
====================
*/
void FuncButton_Touch( void ) {
if ( other.classname == "player" ) {
FuncButton_Trigger();
if ( !( self.spawnflags & SF_BTT_TOUCH_ONLY ) ) {
self.touch = __NULL__;
}
}
}
/*
====================
FuncButton_Blocked
====================
*/
void FuncButton_Blocked( void ) {
if ( self.dmg ) {
Damage_Apply( other, self, self.dmg, other.origin, FALSE );
}
if ( self.wait >= 0 ) {
if ( self.state == STATE_DOWN ) {
FuncButton_MoveAway ();
} else {
FuncButton_MoveBack ();
}
}
}
/*
====================
func_button
Spawn function of a moving door entity
====================
*/
void func_button( void ) {
FuncButton_PrecacheSounds();
Entities_SetMovementDirection();
self.solid = SOLID_BSP;
self.movetype = MOVETYPE_PUSH;
setorigin( self, self.origin );
setmodel( self, self.model );
self.blocked = FuncButton_Blocked;
self.vUse = FuncButton_Trigger;
if ( !self.speed ) {
self.speed = 100;
}
if ( self.spawnflags & SF_BTT_TOUCH_ONLY ) {
self.touch = FuncButton_Touch;
}
self.iUsable = TRUE;
self.pos1 = self.origin;
if ( self.spawnflags & SF_BTT_NOMOVE ) {
self.pos2 = self.pos1;
} else {
self.pos2 = ( self.pos1 + self.movedir * ( fabs( self.movedir * self.size ) - self.lip ) );
}
self.state = STATE_LOWERED;
Entities_RenderSetup();
}

View file

@ -1,283 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_door Spawnflags
=================
*/
void() FuncDoor_MoveAway;
void() FuncDoor_MoveBack;
void() FuncDoor_Touch;
// TODO: Finish these
#define SF_MOV_OPEN 1
#define SF_MOV_UNLINK 4
#define SF_MOV_PASSABLE 8
#define SF_MOV_TOGGLE 32
#define SF_MOV_USE 256
enum {
STATE_RAISED = 0,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
/*
====================
FuncDoor_PrecacheSounds
CS/HL have a lot of door sounds...
====================
*/
void FuncDoor_PrecacheSounds( void ) {
if( self.movesnd > 0 && self.movesnd <= 10 ) {
precache_sound( sprintf( "doors/doormove%d.wav", self.movesnd ) );
} else {
precache_sound( "common/null.wav" );
}
if( self.stopsnd > 0 && self.stopsnd <= 8 ) {
precache_sound( sprintf( "doors/doorstop%d.wav", self.stopsnd ) );
} else {
precache_sound( "common/null.wav" );
}
}
/*
====================
FuncDoor_Arrived
====================
*/
void FuncDoor_Arrived( void ) {
self.state = STATE_RAISED;
if( self.stopsnd > 0 && self.stopsnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%d.wav", self.stopsnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( ( self.spawnflags & SF_MOV_USE ) ) {
self.touch = FuncDoor_Touch;
}
if ( self.wait < 0 ) {
return;
}
if ( !( self.spawnflags & SF_MOV_TOGGLE ) ) {
self.think = FuncDoor_MoveBack;
self.nextthink = ( self.ltime + self.wait );
}
}
/*
====================
FuncDoor_Returned
====================
*/
void FuncDoor_Returned( void ) {
if( self.stopsnd > 0 && self.stopsnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%d.wav", self.stopsnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( ( self.spawnflags & SF_MOV_USE ) ) {
self.touch = FuncDoor_Touch;
}
self.state = STATE_LOWERED;
}
/*
====================
FuncDoor_MoveBack
====================
*/
void FuncDoor_MoveBack( void ) {
if( self.movesnd > 0 && self.movesnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%d.wav", self.movesnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( ( self.spawnflags & SF_MOV_USE ) ) {
self.touch = __NULL__;
}
self.state = STATE_DOWN;
Entities_MoveToDestination ( self.pos1, self.speed, FuncDoor_Returned );
}
/*
====================
FuncDoor_MoveAway
====================
*/
void FuncDoor_MoveAway( void ) {
if ( self.state == STATE_UP ) {
return;
}
if( self.movesnd > 0 && self.movesnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%d.wav", self.movesnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( self.spawnflags & SF_MOV_TOGGLE ) ) {
if ( self.state == STATE_RAISED ) {
self.nextthink = ( self.ltime + self.wait );
return;
}
}
self.state = STATE_UP;
Entities_MoveToDestination ( self.pos2, self.speed, FuncDoor_Arrived );
}
/*
====================
FuncDoor_Trigger
====================
*/
void FuncDoor_Trigger( void ) {
if ( self.fAttackFinished > self.ltime ) {
return;
}
self.fAttackFinished = self.ltime + self.wait;
// Only trigger stuff when we are done moving
if ( ( self.state == STATE_RAISED ) || ( self.state == STATE_LOWERED ) ) {
if ( self.delay > 0 ) {
Entities_UseTargets_Delay( self.delay );
} else {
Entities_UseTargets();
}
}
if ( ( self.state == STATE_UP ) || ( self.state == STATE_RAISED ) ){
FuncDoor_MoveBack();
return;
}
FuncDoor_MoveAway();
}
/*
====================
FuncDoor_Touch
====================
*/
void FuncDoor_Touch( void ) {
if ( self.spawnflags & SF_MOV_TOGGLE ) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin_z <= self.maxs_z - 2 ) {
FuncDoor_Trigger();
}
}
}
/*
====================
FuncDoor_Blocked
====================
*/
void FuncDoor_Blocked( void ) {
if( self.dmg ) {
Damage_Apply( other, self, self.dmg, other.origin, FALSE );
}
if ( self.wait >= 0 ) {
if ( self.state == STATE_DOWN ) {
FuncDoor_MoveAway ();
} else {
FuncDoor_MoveBack ();
}
}
}
/*
====================
func_door
Spawn function of a moving door entity
====================
*/
void func_door( void ) {
static void func_door_respawn( void ) {
self.solid = SOLID_BSP;
self.movetype = MOVETYPE_PUSH;
setorigin( self, self.origin );
setmodel( self, self.model );
self.blocked = FuncDoor_Blocked;
self.vUse = FuncDoor_Trigger;
if ( self.wait == -1 ) {
self.spawnflags = self.spawnflags | SF_MOV_TOGGLE;
}
if ( !self.speed ) {
self.speed = 100;
}
if ( !self.dmg ) {
self.dmg = 2;
}
if ( self.spawnflags & SF_MOV_USE ) {
self.iUsable = TRUE;
} else {
self.touch = FuncDoor_Touch;
}
self.state = STATE_LOWERED;
self.pos1 = self.origin;
self.pos2 = ( self.pos1 + self.movedir * ( fabs( self.movedir * self.size ) - self.lip ) );
if ( self.spawnflags & SF_MOV_OPEN ) {
setorigin( self, self.pos2 );
self.pos2 = self.pos1;
self.pos1 = self.origin;
}
}
FuncDoor_PrecacheSounds();
Entities_SetMovementDirection();
func_door_respawn();
Entities_InitRespawnable( func_door_respawn );
Entities_RenderSetup();
}

View file

@ -1,275 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_door_rotating Spawnflags
=================
*/
enumflags {
SF_ROT_OPEN,
SF_ROT_REVERSE,
SF_ROT_UNLINK,
SF_ROT_ONEWAY,
SF_ROT_TOGGLE,
SF_ROT_XAXIS,
SF_ROT_YAXIS,
SF_ROT_USE
};
void FuncDoorRotate_RotateAway( void );
void FuncDoorRotate_RotateBack( void );
void FuncDoorRotate_Touch( void );
/*
=================
FuncDoorRotate_Arrived
=================
*/
void FuncDoorRotate_Arrived( void ) {
self.state = STATE_RAISED;
if( self.stopsnd > 0 && self.stopsnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%d.wav", self.stopsnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !(self.spawnflags & SF_ROT_USE) ) {
self.touch = FuncDoorRotate_Touch;
}
if ( self.wait < 0 ) {
return;
}
self.think = FuncDoorRotate_RotateBack;
self.nextthink = ( self.ltime + self.wait );
}
/*
=================
FuncDoorRotate_Returned
=================
*/
void FuncDoorRotate_Returned( void ) {
if ( !(self.spawnflags & SF_ROT_USE) ) {
self.touch = FuncDoorRotate_Touch;
}
self.state = STATE_LOWERED;
}
/*
=================
FuncDoorRotate_RotateBack
=================
*/
void FuncDoorRotate_RotateBack( void ) {
if ( self.movesnd > 0 && self.movesnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%d.wav", self.movesnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !(self.spawnflags & SF_ROT_USE) ) {
self.touch = __NULL__;
}
self.state = STATE_DOWN;
Entities_RotateToDestination( self.pos1, self.speed, FuncDoorRotate_Returned );
}
/*
=================
FuncDoorRotate_Away
=================
*/
void FuncDoorRotate_RotateAway( void ) {
float fDirection = 1.0;
if ( self.state == STATE_UP ) {
return;
}
if ( self.movesnd > 0 && self.movesnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%d.wav", self.movesnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( self.state == STATE_RAISED ) {
self.nextthink = ( self.ltime + self.wait );
return;
}
self.state = STATE_UP;
if ( !( self.spawnflags & SF_ROT_ONEWAY ) ) {
vector vDifference = eActivator.origin - self.origin;
vector vAngles = eActivator.angles;
vAngles_x = vAngles_z = 0;
makevectors( vAngles );
vector vNext = ( eActivator.origin + ( v_forward * 10 ) ) - self.origin;
if ( ( ( vDifference_x * vNext_y ) - ( vDifference_y * vNext_x ) ) < 0 ) {
fDirection = -1.0;
}
}
Entities_RotateToDestination( self.pos2 * fDirection, self.speed, FuncDoorRotate_Arrived );
}
/*
=================
brush_rotate_trigger - What happens when you +use the brush or trigger it
=================
*/
void FuncDoorRotate_Trigger( void ) {
if ( self.fAttackFinished > time ) {
return;
}
self.fAttackFinished = time + self.wait;
if ( ( self.state == STATE_UP ) || ( self.state == STATE_RAISED ) ) {
FuncDoorRotate_RotateBack();
return;
}
FuncDoorRotate_RotateAway();
if ( self.delay ) {
Entities_UseTargets_Delay( self.delay );
} else {
Entities_UseTargets();
}
}
/*
=================
FuncDoorRotate_Touch
=================
*/
void FuncDoorRotate_Touch( void ) {
if ( self.spawnflags & SF_ROT_TOGGLE ) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin_z <= self.maxs_z - 2 ) {
eActivator = other;
FuncDoorRotate_Trigger();
}
}
}
/*
=================
FuncDoorRotate_Blocked
=================
*/
void FuncDoorRotate_Blocked( void ) {
if ( self.dmg ) {
Damage_Apply( other, self, self.dmg, other.origin, FALSE );
}
if ( self.wait >= 0 ) {
if ( self.state == STATE_DOWN ) {
FuncDoorRotate_RotateAway ();
} else {
FuncDoorRotate_RotateBack ();
}
}
}
/*
=================
BrushRotate
Brush entity that rotates into a specific direction.
Has the ability to trigger an object once touched, used or triggered otherwise.
=================
*/
void func_door_rotating( void ) {
static void func_door_rotating_respawn( void ) {
self.solid = SOLID_BSP;
self.movetype = MOVETYPE_PUSH;
setorigin( self, self.origin );
setmodel( self, self.model );
self.blocked = FuncDoorRotate_Blocked;
self.vUse = FuncDoorRotate_Trigger;
if ( self.spawnflags & SF_ROT_USE ) {
self.iUsable = TRUE;
} else {
self.touch = FuncDoorRotate_Touch;
}
if ( !self.speed ) {
self.speed = 100;
}
if ( self.wait == 0 ) {
self.wait = 4;
}
self.state = STATE_LOWERED;
self.pos1 = self.angles;
// Only do Y
if ( self.spawnflags & SF_ROT_XAXIS ) {
self.pos2_y = self.pos1_y + self.distance;
}
// Only do X
if ( self.spawnflags & SF_ROT_YAXIS ) {
self.pos2_x = self.pos1_x + self.distance;
}
// only do Y by default
if ( !( self.spawnflags & SF_ROT_YAXIS ) && !( self.spawnflags & SF_ROT_XAXIS ) ) {
self.pos2_y = self.pos1_y + self.distance;
}
if ( self.spawnflags & SF_ROT_OPEN ) {
vector vTemp = self.pos2;
self.pos2 = self.pos1;
self.pos1 = vTemp;
self.angles = self.pos1;
}
}
FuncDoor_PrecacheSounds();
Entities_SetMovementDirection();
func_door_rotating_respawn();
Entities_InitRespawnable( func_door_rotating_respawn );
Entities_RenderSetup();
}

View file

@ -1,78 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
TODO: This gamemode is odd about balancing, right now the last surviving terrorist
will decide the match. Still have to think about what rules to set up.
*/
/*
=================
func_escapezone_touch
=================
*/
void func_escapezone_touch( void ) {
if ( ( other.classname == "player" ) && ( other.team == TEAM_T ) ) {
entity eOld = self;
self = other;
Spawn_MakeSpectator();
self.classname = "player";
forceinfokey( self, "*dead", "0" );
self.health = 0;
Rules_CountPlayers();
self = eOld;
if ( iAlivePlayers_T == 0 ) {
Rules_RoundOver( TEAM_T, 2500, FALSE );
}
}
}
/*
=================
SPAWN: func_escapezone
Entry function for the terrorist escape zone
=================
*/
void func_escapezone( void ) {
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
if ( self.model ) {
setmodel( self, self.model );
} else {
setsize( self, self.mins, self.maxs );
}
self.model = 0;
self.touch = func_escapezone_touch;
iEscapeZones++;
}

View file

@ -1,114 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_hostage_rescue_touch
=================
*/
void func_hostage_rescue_touch( void ) {
if ( ( other.classname == "player" ) && ( other.team == TEAM_CT ) ) {
other.fInHostageZone = TRUE; // Note: this will be cleared every frame inside SV_RunClientCommand
} else if ( other.classname == "hostage_entity" ) {
if ( self.solid == SOLID_NOT ) {
return;
}
Radio_BroadcastMessage( RADIO_RESCUED );
iHostagesRescued++;
Money_AddMoney( other.eUser, 1000 );
Money_QueTeamReward( TEAM_CT, 800 );
if ( other.eTargetPoint != other.eUser ) {
remove( other.eTargetPoint );
}
other.eTargetPoint = other.eUser = world;
entity eOld = self;
self = other;
Entities_Remove();
self = eOld;
if ( iHostagesRescued >= iHostagesMax ) {
// TODO: Broadcast_Print: All Hostages have been rescued!
Rules_RoundOver( TEAM_CT, 0, FALSE );
}
}
}
/*
=================
SPAWN: func_hostage_rescue
Entry function for the rescue area-markings.
=================
*/
void func_hostage_rescue( void ) {
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
if ( self.model ) {
setmodel( self, self.model );
} else {
setsize( self, self.mins, self.maxs );
}
self.model = 0;
self.touch = func_hostage_rescue_touch;
iRescueZones++;
}
void info_hostage_rescue( void ) {
self.mins = '-128 -128 -36';
self.maxs = '128 128 36';
func_hostage_rescue();
}
/*
=================
Game_CreateRescueZones
Called by StartFrame if we somehow got no rescue zones
=================
*/
void Game_CreateRescueZones( void ) {
entity eFind = findchain( classname, "info_player_start" );
while ( eFind ) {
entity eRescueZone = spawn();
setorigin( eRescueZone, eFind.origin );
entity eOld = self;
self = eRescueZone;
info_hostage_rescue();
self = eOld;
eFind = eFind.chain;
}
}

View file

@ -1,104 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
// Uncomment this once FTEs engine ladder is fixed?
//#define FTE_LADDER
/*
=================
func_ladder_sound
=================
*/
void func_ladder_sound( entity target ) {
if ( ( target.velocity_z == 0 ) || ( target.fStepTime > time ) ) {
return;
}
float vStep = target.velocity_z;
if ( vStep < 0 ) {
vStep *= -1.0;
}
float fForce = vStep;
float fDelay = clamp( 0.1, 1 / ( fForce / 90 ), 1 );
sound( target, CHAN_BODY, sprintf( "player/pl_ladder%d.wav", floor( random() * 4 ) + 1 ), 0.5, ATTN_IDLE );
target.fStepTime = ( time + fDelay );
}
/*
=================
func_ladder_touch
=================
*/
void func_ladder_touch( void ) {
if ( other.classname != "player" ) {
return;
}
#ifndef FTE_LADDER
vector vPlayerVector;
makevectors( other.v_angle );
vPlayerVector = v_forward;
vPlayerVector = ( vPlayerVector * 240 );
if ( other.movement_x > 0 ) {
other.velocity = vPlayerVector;
} else {
other.velocity = '0 0 0';
}
#endif
func_ladder_sound( other );
}
/*
=================
SPAWN: func_ladder
A trigger like brush that allows you to 'climb' up or down
=================
*/
void func_ladder( void ) {
precache_sound( "player/pl_ladder1.wav" );
precache_sound( "player/pl_ladder2.wav" );
precache_sound( "player/pl_ladder3.wav" );
precache_sound( "player/pl_ladder4.wav" );
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
setmodel( self, self.model );
self.model = 0;
#ifdef FTE_LADDER
self.skin = CONTENT_LADDER;
self.alpha = 0.001;
#endif
self.touch = func_ladder_touch;
}

View file

@ -1,84 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
SPAWN: func_pushable
Entry function for the brushes that players can push.
Pushables are an extension of breakables, so they mostly
explain themselves.
=================
*/
void func_pushable( void ) {
static void func_pushable_touch( void ) {
if ( other.classname == "player" ) {
func_breakable_touch();
if ( other.absmin_z <= self.maxs_z - 2 ) {
self.movedir = other.movement;
self.v_angle = other.angles;
}
}
}
static void func_pushable_use( void ) {
if ( eActivator.classname != "player" ) {
if ( self.health > 0 ) {
func_breakable_use();
return;
}
}
self.movedir = eActivator.movement;
self.v_angle = eActivator.angles;
}
static void func_pushable_physics( void ) {
input_movevalues = [ self.movedir_x * 100, self.movedir_y * 100, 0 ];
input_impulse = input_buttons = 0;
input_angles = self.v_angle;
input_timelength = frametime;
self.movedir = '0 0 0';
runstandardplayerphysics( self );
}
static void func_pushable_respawn( void ) {
self.takedamage = DAMAGE_YES;
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_WALK;
self.customphysics = func_pushable_physics;
self.touch = func_pushable_touch;
self.vUse = func_pushable_use;
self.vPain = func_breakable_pain;
self.vDeath = func_breakable_die;
self.iBleeds = FALSE;
self.iUsable = TRUE;
}
func_wall();
func_pushable_respawn();
Entities_InitRespawnable( func_pushable_respawn );
}

View file

@ -1,70 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_vip_safetyzone_touch
=================
*/
void func_vip_safetyzone_touch( void ) {
if ( ( other.classname == "player" ) && ( other.team == TEAM_VIP ) ) {
Rules_RoundOver( TEAM_CT, 2500, FALSE );
entity eOld = self;
self = other;
Spawn_MakeSpectator();
self.classname = "player";
self.team = TEAM_CT;
forceinfokey( self, "*dead", "0" );
iAlivePlayers_CT--;
self = eOld;
}
}
/*
=================
SPAWN: func_vip_safetyzone
Entry function for the VIP escape zone
=================
*/
void func_vip_safetyzone( void ) {
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
if ( self.model ) {
setmodel( self, self.model );
} else {
setsize( self, self.mins, self.maxs );
}
self.model = 0;
self.touch = func_vip_safetyzone_touch;
iVIPZones++;
}

View file

@ -1,188 +0,0 @@
/*
Copyright 2016-2018 Marco "eukara" Hladik
MIT LICENSE
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
.entity eDriver;
.entity eVehicle;
.float height;
enum {
STATE_REVERSE = -1,
STATE_OFF,
STATE_GEAR1,
STATE_GEAR2,
STATE_GEAR3
};
/*
=================
SPAWN: func_vehicle
The function that creates life
=================
*/
void func_vehicle_physics( void ) {
if ( self.eDriver ) {
// Input, gears
if ( self.fAttackFinished < time ) {
if ( self.eDriver.movement_x > 0 ) {
self.state++;
if ( self.state > STATE_GEAR3 ) {
self.state = STATE_GEAR3;
}
} else if ( self.eDriver.movement_x < 0 ) {
self.state--;
if ( self.state < STATE_REVERSE ) {
self.state = STATE_REVERSE;
}
}
self.fAttackFinished = time + 0.25f;
}
if ( self.eDriver.movement_y > 0 ) {
self.angles_y -= frametime * 100;
} else if ( self.eDriver.movement_y < 0 ) {
self.angles_y += frametime * 100;
}
} else {
}
// Figure out the next position
makevectors( self.angles + self.v_angle );
tracebox( self.origin, self.mins, self.maxs, self.origin + ( ( v_forward * ( 100 * self.state ) ) * frametime ), FALSE, self );
setorigin( self, self.origin + ( ( v_forward * ( 100 * self.state ) ) * frametime ) );
// Update driver position as well
if ( self.eDriver ) {
setorigin( self.eDriver, self.eDriver.origin + ( ( v_forward * ( 100 * self.state ) ) * frametime ) );
}
}
/*
=================
SPAWN: func_vehicle
The function that creates life
=================
*/
void func_vehicle( void ) {
static void func_vehicle_setup( void ) {
entity eStop1 = find( world, targetname, self.target );
bprint( sprintf( "self.origin: %v targetpos: %v\n", self.origin, eStop1.origin ) );
setorigin( self, eStop1.origin );
entity eStop2 = find( world, targetname, eStop1.target );
self.v_angle = vectoangles( eStop2.origin - self.origin );
bprint( sprintf( "self.origin: %v target2pos: %v & angles: %v\n", self.origin, eStop2.origin, self.v_angle ) );
setorigin( self, self.origin + [ 0, 0, self.height ] );
}
static void func_vehicle_use( void ) {
bprint( "Used!\n" );
if ( self.eDriver ) {
if ( self.eDriver != eActivator ) {
// Someone else is using it, don't let him
return;
} else {
// Unassign driver
self.eDriver = __NULL__;
}
} else {
self.eDriver = eActivator;
}
}
static void func_vehicle_respawn( void ) {
func_vehicle_setup();
self.angles = '0 0 0';
}
self.solid = SOLID_BSP;
self.customphysics = func_vehicle_physics;
self.iUsable = TRUE;
self.vUse = func_vehicle_use;
setmodel( self, self.model );
Entities_RenderSetup();
Entities_InitRespawnable( func_vehicle_respawn );
}
void path_track( void ) {
}
/*
=================
SPAWN: func_vehiclecontrols
The function that enables life
=================
*/
/*void func_vehiclecontrols2( void ) {
static void func_vehiclecontrols_setup( void ) {
if ( !self.target ) {
objerror( "func_vehiclecontrols without func_vehicle" );
}
self.owner = find( world, targetname, self.target );
if ( !self.owner ) {
objerror( "func_vehiclecontrols' target cannot be found" );
} else {
self.owner.owner = self;
}
self.owner.vControlPos = self.owner.origin - self.origin;
}
static void func_vehiclecontrols_respawn( void ) {
self.angles = '0 0 0';
}
static void func_vehiclecontrols_use( void ) {
bprint( "Used!\n" );
if ( self.owner.eDriver ) {
if ( self.owner.eDriver != eActivator ) {
// Someone else is using it, don't let him
return;
} else {
// Unassign driver
self.owner.eDriver == __NULL__;
}
} else {
self.owner.eDriver = eActivator;
self.owner.vPlayerPos = self.owner.origin - eActivator.origin;
}
}
self.solid = SOLID_BSP;
self.iUsable = TRUE;
self.vUse = func_vehiclecontrols_use;
setmodel( self, self.model );
Entities_RenderSetup();
Entities_InitRespawnable( func_vehiclecontrols_respawn );
self.think = func_vehiclecontrols_setup;
self.nextthink = time + 0.1f;
}*/

View file

@ -180,7 +180,7 @@ void Player_UseDown( void ) {
vSource = self.origin + self.view_ofs;
traceline ( vSource, vSource + ( v_forward * 64 ), FALSE, self);
if (trace_ent.gflags & GF_USABLE) {
if (trace_ent.PlayerUse) {
if ( ( trace_ent.classname != "c4bomb" ) && ( trace_ent.classname != "func_pushable" ) ) {
self.flags = ( self.flags - FL_USERELEASED );
sound( self, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE );

View file

@ -194,15 +194,15 @@ void Rules_Restart( int iWipe ) {
}
}
// Respawn all the entities
for ( entity eFind = world; ( eFind = findfloat( eFind, fRespawns, TRUE ) ); ) {
self = eFind;
Entities_Respawn();
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
self = eOld;
Timer_Begin( autocvar_mp_freezetime, GAME_FREEZE );
Money_ResetTeamReward();
fDefuseProgress = 0;

View file

@ -0,0 +1,35 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class func_bomb_target
{
void() func_bomb_target;
virtual void() touch;
};
void func_bomb_target::touch(void)
{
if (iBombPlanted == TRUE) {
return;
}
/* This will be cleared every frame inside SV_RunClientCommand */
if ((other.classname == "player") && (other.team == TEAM_T)) {
other.fInBombZone = TRUE;
}
}
void func_bomb_target::func_bomb_target(void)
{
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
setmodel(this, model);
model = 0;
iBombZones++;
}

View file

@ -24,52 +24,48 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
=================
func_buyzone_touch
=================
*/
void func_buyzone_touch( void ) {
if( ( other.classname == "player" ) && ( other.team == self.team ) ) {
other.fInBuyZone = TRUE; // Note: this will be cleared every frame inside SV_RunClientCommand
class func_buyzone
{
void() func_buyzone;
virtual void() touch;
};
void func_buyzone::touch(void)
{
/* This will be cleared every frame inside SV_RunClientCommand */
if((other.classname == "player" ) && (other.team == self.team)) {
other.fInBuyZone = TRUE;
}
}
/*
=================
SPAWN: func_buyzone
Entry function for the buyzone area-markings.
=================
*/
void func_buyzone( void ) {
if ( autocvar_fcs_knifeonly == TRUE ) {
void func_buyzone::func_buyzone(void)
{
if (autocvar_fcs_knifeonly == TRUE) {
remove( self );
return;
}
if ( autocvar_fcs_swapteams == TRUE ) {
if (self.team == TEAM_T) {
self.team = TEAM_CT;
} else if (self.team == TEAM_CT) {
self.team = TEAM_T;
if (autocvar_fcs_swapteams == TRUE) {
if (team == TEAM_T) {
team = TEAM_CT;
} else if (team == TEAM_CT) {
team = TEAM_T;
}
}
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
if ( self.model ) {
setmodel( self, self.model );
angles = '0 0 0';
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if (model) {
setmodel(this, model);
} else {
self.mins = '-128 -128 -36';
self.maxs = '128 128 36';
setsize( self, self.mins, self.maxs );
mins = '-128 -128 -36';
maxs = '128 128 36';
setsize(this, mins, maxs);
}
self.model = 0;
self.touch = func_buyzone_touch;
model = 0;
iBuyZones++;
}
@ -95,7 +91,7 @@ void Game_CreateBuyZones( void ) {
entity eBuyZoneT = spawn();
setorigin( eBuyZoneT, eFind.origin );
self = eBuyZoneT;
func_buyzone();
spawnfunc_func_buyzone();
self.team = TEAM_T;
eFind = eFind.chain;
@ -111,7 +107,7 @@ void Game_CreateBuyZones( void ) {
entity eBuyZoneCT = spawn();
setorigin( eBuyZoneCT, eFind.origin );
self = eBuyZoneCT;
func_buyzone();
spawnfunc_func_buyzone();
self.team = TEAM_CT;
eFind = eFind.chain;

View file

@ -0,0 +1,70 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
/*
TODO: This gamemode is odd about balancing, right now the last surviving terrorist
will decide the match. Still have to think about what rules to set up.
*/
class func_escapezone
{
void() func_escapezone;
virtual void() touch;
};
void Escape_Touch(entity targ)
{
entity eOld = self;
self = targ;
Spawn_MakeSpectator();
self.classname = "player";
forceinfokey( self, "*dead", "0" );
self.health = 0;
Rules_CountPlayers();
self = eOld;
}
/*
=================
func_escapezone_touch
=================
*/
void func_escapezone::touch(void)
{
if ((other.classname == "player") && (other.team == TEAM_T)) {
Escape_Touch(other);
if (iAlivePlayers_T == 0) {
Rules_RoundOver(TEAM_T, 2500, FALSE);
}
}
}
/*
=================
SPAWN: func_escapezone
Entry function for the terrorist escape zone
=================
*/
void func_escapezone::func_escapezone(void)
{
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if ( model ) {
setmodel( self, model );
} else {
setsize( self, mins, maxs );
}
model = 0;
iEscapeZones++;
}

View file

@ -0,0 +1,58 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class func_hostage_rescue
{
void() func_hostage_rescue;
virtual void() touch;
};
void func_hostage_rescue::touch(void)
{
if ((other.classname == "player" ) && ( other.team == TEAM_CT )) {
/* This will be cleared every frame inside SV_RunClientCommand */
other.fInHostageZone = TRUE;
} else if (other.classname == "hostage_entity") {
hostage_entity hosty = (hostage_entity)other;
if (solid == SOLID_NOT) {
return;
}
Radio_BroadcastMessage(RADIO_RESCUED);
iHostagesRescued++;
Money_AddMoney(hosty.m_eUser, 1000);
Money_QueTeamReward(TEAM_CT, 800);
CBaseEntity targa = (CBaseEntity)other;
targa.Hide();
if (iHostagesRescued >= iHostagesMax) {
// TODO: Broadcast_Print: All Hostages have been rescued!
Rules_RoundOver(TEAM_CT, 0, FALSE);
}
}
}
void func_hostage_rescue::func_hostage_rescue( void )
{
angles = '0 0 0';
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if (model) {
setmodel(this, model);
} else {
mins = '-128 -128 -36';
maxs = '128 128 36';
setsize(this, mins, maxs);
}
model = 0;
iRescueZones++;
}

View file

@ -0,0 +1,50 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class func_vip_safetyzone
{
void() func_vip_safetyzone;
virtual void() touch;
};
/* Hack! Make this better? */
void VIP_Rescue(entity targ)
{
entity eOld = self;
self = other;
Spawn_MakeSpectator();
self.classname = "player";
self.team = TEAM_CT;
forceinfokey(self, "*dead", "0");
iAlivePlayers_CT--;
self = eOld;
}
void func_vip_safetyzone::touch(void)
{
if ((other.classname == "player") && (other.team == TEAM_VIP)) {
Rules_RoundOver(TEAM_CT, 2500, FALSE);
VIP_Rescue(other);
}
}
void func_vip_safetyzone::func_vip_safetyzone(void)
{
angles = '0 0 0';
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if (model) {
setmodel(this, model);
} else {
setsize(this, mins, maxs);
}
model = 0;
iVIPZones++;
}

View file

@ -0,0 +1,187 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enum {
HOSTAGE_IDLE,
HOSTAGE_WALK,
HOSTAGE_RUN
};
enum {
HOSA_WALK,
HOSA_WALKSCARED,
HOSA_RUN,
HOSA_RUNSCARED,
HOSA_RUNLOOK,
HOSA_180LEFT,
HOSA_180RIGHT,
HOSA_FLINCH,
HOSA_PAIN,
HOSA_PAINLEFT,
HOSA_PAINRIGHT,
HOSA_PAINLEGLEFT,
HOSA_PAINLEGRIGHT,
HOSA_IDLE1,
HOSA_IDLE2,
HOSA_IDLE3,
HOSA_IDLE4,
HOSA_IDLE5,
HOSA_IDLE6,
HOSA_SCARED_END,
HOSA_SCARED1,
HOSA_SCARED2,
HOSA_SCARED3,
HOSA_SCARED4,
HOSA_PANIC,
HOSA_FEAR1,
HOSA_FEAR2,
HOSA_CRY,
HOSA_SCI1,
HOSA_SCI2,
HOSA_SCI3,
HOSA_DIE_SIMPLE,
HOSA_DIE_FORWARD1,
HOSA_DIE_FORWARD2,
HOSA_DIE_BACKWARD,
HOSA_DIE_HEADSHOT,
HOSA_DIE_GUTSHOT,
HOSA_LYING1,
HOSA_LYING2,
HOSA_DEADSIT,
HOSA_DEADTABLE1,
HOSA_DEADTABLE2,
HOSA_DEADTABLE3
};
class hostage_entity:CBaseEntity
{
entity m_eUser;
int m_iUsed;
void() hostage_entity;
virtual void() Hide;
virtual void() Respawn;
virtual void() PlayerUse;
virtual void(int) vPain;
virtual void(int) vDeath;
virtual void() Physics;
};
void hostage_entity::Physics(void)
{
input_movevalues = [0,0,0];
input_impulse = 0;
input_buttons = 0;
if (m_eUser!= world) {
vector enda = vectoangles(m_eUser.origin - origin);
enda[0] = 0;
enda[1] = Math_FixDelta(enda[1]);
enda[2] = 0;
v_angle = enda;
if (vlen(m_eUser.origin - origin) > 128) {
input_movevalues[0] = 240;
}
}
input_timelength = frametime;
input_angles = v_angle;
movetype = MOVETYPE_WALK;
runstandardplayerphysics(this);
Footsteps_Update();
angles = v_angle;
movetype = MOVETYPE_NONE;
}
void hostage_entity::PlayerUse(void)
{
if (eActivator.team == TEAM_CT) {
if ((m_eUser == world)) {
// Only give cash to the CT for using it for the first time
if (m_iUsed == FALSE) {
Money_AddMoney(eActivator, 150);
sound(this, CHAN_VOICE, sprintf("hostage/hos%d.wav", random(1, 6)), 1.0, ATTN_IDLE);
m_iUsed = TRUE;
}
m_eUser = eActivator;
} else {
m_eUser = world;
}
}
}
void hostage_entity::vPain(int iHitBody)
{
frame = HOSA_FLINCH + floor(random(0, 5));
}
void hostage_entity::vDeath(int iHitBody)
{
Radio_BroadcastMessage(RADIO_HOSDOWN);
frame = HOSA_DIE_SIMPLE + floor(random(0, 6));
solid = SOLID_NOT;
takedamage = DAMAGE_NO;
customphysics = Empty;
}
void hostage_entity::Hide(void)
{
setmodel(this, "");
m_eUser = world;
solid = SOLID_NOT;
movetype = MOVETYPE_NONE;
customphysics = __NULL__;
}
void hostage_entity::Respawn(void)
{
v_angle[0] = Math_FixDelta(m_oldAngle[0]);
v_angle[1] = Math_FixDelta(m_oldAngle[1]);
v_angle[2] = Math_FixDelta(m_oldAngle[2]);
setorigin(this, m_oldOrigin);
angles = v_angle;
solid = SOLID_SLIDEBOX;
movetype = MOVETYPE_NONE;
setmodel(this, m_oldModel);
setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
m_eUser = world;
iBleeds = TRUE;
takedamage = DAMAGE_YES;
style = HOSTAGE_IDLE;
customphysics = Physics;
frame = HOSA_IDLE1;
health = 100;
velocity = [0,0,0];
m_iUsed = FALSE;
}
void hostage_entity::hostage_entity(void)
{
// Path hack, FIXME do it a better way
if (model == "/models/hostage.mdl") {
model = "";
}
if (!model) {
model = "models/hostage.mdl";
}
CBaseEntity::CBaseEntity();
precache_model(m_oldModel);
setmodel(this, m_oldModel);
iHostagesMax = iHostagesMax + 1;
Respawn();
}

View file

@ -0,0 +1,33 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
void info_hostage_rescue(void)
{
spawnfunc_func_hostage_rescue();
}
/*
=================
Game_CreateRescueZones
Called by StartFrame if we somehow got no rescue zones
=================
*/
void Game_CreateRescueZones(void)
{
entity a;
int count = 0;
for (a = world; (a = find(a, classname, "info_player_start"));) {
func_hostage_rescue zone = spawn(func_hostage_rescue);
setorigin(zone, a.origin);
count++;
}
print(sprintf("Game: Created %i func_hostage_rescue\n", count));
}

View file

@ -48,7 +48,10 @@ Money.c
../Shared/spraylogo.cpp
../Shared/pmove.c
hostage_entity.cpp
func_hostage_rescue.cpp
info_hostage_rescue.cpp
func_vip_safetyzone.cpp
info_map_parameters.cpp
Vox.c
@ -58,16 +61,9 @@ TraceAttack.c
Rules.c
Timer.c
EntHostage.c
Entities.c
FuncHostageRescue.c
FuncEscapeZone.c
FuncBombTarget.c
FuncBuyZone.c
FuncVIPSafetyZone.c
ArmouryEntity.c
func_bomb_target.cpp
func_buyzone.cpp
func_escapezone.cpp
Bot/Bot.h
Bot/Way.c

View file

@ -114,7 +114,7 @@ static void WeaponC4BOMB_Think( void ) {
if ( ( eBombChain.classname == "func_bomb_target" ) ) {
entity eOld = self;
self = eBombChain;
Entities_UseTargets();
//Entities_UseTargets();
self = eOld;
}
eBombChain = eBombChain.chain;
@ -160,7 +160,6 @@ void WeaponC4BOMB_Drop( vector vBombPos, vector vNormal ) {
eBomb.customphysics = WeaponC4BOMB_Think;
eBomb.fAttackFinished = time + autocvar_mp_c4timer;
eBomb.gflags = GF_USABLE;
eBomb.PlayerUse = WeaponC4BOMB_Use;
eBomb.owner = self;

View file

@ -1,6 +1,8 @@
/***
*
* Copyright (c) 2000-2019, Vera Visions. All rights reserved.
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/

View file

@ -28,14 +28,25 @@ Notes
class cycler:CBaseEntity
{
void() cycler;
virtual void(entity, int, int) vPain;
};
void cycler::vPain(entity attacker, int type, int damage)
{
if (frame >= modelframecount(modelindex)) {
frame = 0;
} else {
frame += 1;
}
health = 9999;
}
void cycler::cycler(void)
{
precache_model(model);
CBaseEntity::CBaseEntity();
setmodel(this, model);
precache_model(m_oldModel);
setmodel(this, m_oldModel);
solid = SOLID_BBOX;
takedamage = DAMAGE_YES;
health = 9999;
}

View file

@ -0,0 +1,27 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
/* https://twhl.info/wiki/page/cycler_sprite_(Half-Life) */
enumflags
{
ENVS_STARTON,
ENVS_PLAYONCE
};
class cycler_sprite:CBaseEntity
{
void() cycler_sprite;
};
void cycler_sprite::cycler_sprite(void)
{
CBaseEntity::CBaseEntity();
precache_model(m_oldModel);
Respawn();
}

View file

@ -12,21 +12,11 @@
enumflags
{
GF_USABLE,
GF_CANRESPAWN,
GF_CANBLEED,
GF_USE_RELEASED,
GF_BUFF_BLEED,
GF_BUFF_COMPUSURE,
GF_BUFF_WILLPOWER,
GF_CARRIES_FLAG,
GF_IN_VEHICLE,
GF_IS_HEALING,
GF_FROZEN,
GF_TORCH,
GF_SEMI_TOGGLED,
GF_BLOCKING,
GF_BOT_POI
GF_SEMI_TOGGLED
};
void Effect_CreateSpark(vector pos, vector ang);

View file

@ -6,7 +6,7 @@
*
****/
/* https://twhl.info/wiki/page/env_sprite_(Half-Life) */
/* https://twhl.info/wiki/page/env_glow_(Half-Life) */
enumflags
{

View file

@ -17,6 +17,11 @@ enumflags
class env_sprite:CBaseTrigger
{
int m_iToggled;
float m_flFramerate;
float m_flScale;
float m_flAlpha;
float m_flEffects;
void() env_sprite;
virtual void() Trigger;
virtual float(entity, float) Network;
@ -33,24 +38,27 @@ float env_sprite::Network(entity pvsent, float flags)
WriteCoord(MSG_ENTITY, origin_y);
WriteCoord(MSG_ENTITY, origin_z);
WriteFloat(MSG_ENTITY, modelindex);
WriteFloat(MSG_ENTITY, framerate);
WriteFloat(MSG_ENTITY, scale);
WriteFloat(MSG_ENTITY, alpha);
WriteFloat(MSG_ENTITY, m_flFramerate);
WriteFloat(MSG_ENTITY, m_flScale);
WriteFloat(MSG_ENTITY, m_flAlpha);
WriteFloat(MSG_ENTITY, effects);
return TRUE;
}
void env_sprite::NetworkOnce(void)
{
WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET );
WriteByte(MSG_ENTITY, EV_SPRITE);
WriteCoord(MSG_ENTITY, origin_x);
WriteCoord(MSG_ENTITY, origin_y);
WriteCoord(MSG_ENTITY, origin_z);
WriteFloat(MSG_ENTITY, modelindex);
WriteFloat(MSG_ENTITY, framerate);
WriteFloat(MSG_ENTITY, scale);
WriteFloat(MSG_ENTITY, alpha);
WriteFloat(MSG_ENTITY, m_flFramerate);
WriteFloat(MSG_ENTITY, m_flScale);
WriteFloat(MSG_ENTITY, m_flAlpha);
WriteFloat(MSG_ENTITY, effects);
msg_entity = this;
multicast( origin, MULTICAST_PVS );
}
void env_sprite::Trigger(void)
@ -65,6 +73,22 @@ void env_sprite::Trigger(void)
void env_sprite::env_sprite(void)
{
for (int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2) {
switch ( argv( i ) ) {
case "framerate":
m_flFramerate = stof(argv(i + 1));
break;
case "scale":
m_flScale = stof(argv(i + 1));
break;
case "alpha":
m_flAlpha = stof(argv(i + 1));
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
precache_model(m_oldModel);
Respawn();

View file

@ -20,7 +20,7 @@ enumflags
SF_PRESSURE
};
class func_breakable : CBaseTrigger
class func_breakable:CBaseTrigger
{
float m_iMaterial;
float m_flDelay;
@ -33,70 +33,70 @@ class func_breakable : CBaseTrigger
virtual void() Trigger;
virtual void() PlayerTouch;
/*virtual void() PressureDeath;*/
virtual void( entity eAttacker, int iType, int iDamage ) vPain;
virtual void( entity eAttacker, int iType, int iDamage ) vDeath;
virtual void(entity eAttacker, int iType, int iDamage) vPain;
virtual void(entity eAttacker, int iType, int iDamage) vDeath;
};
void func_breakable :: vPain ( entity attacker, int type, int damage )
void func_breakable::vPain (entity attacker, int type, int damage)
{
if (spawnflags & SF_TRIGGER) {
return;
}
if (serverkeyfloat("*bspversion") != 30) {
return;
}
switch ( m_iMaterial ) {
switch (m_iMaterial) {
case MATERIAL_GLASS:
case MATERIAL_COMPUTER:
case MATERIAL_GLASS_UNBREAKABLE:
sound( self, CHAN_VOICE, sprintf( "debris/glass%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
sound(self, CHAN_VOICE, sprintf("debris/glass%d.wav", random(1, 4)), 1.0, ATTN_NORM);
break;
case MATERIAL_WOOD:
sound( self, CHAN_VOICE, sprintf( "debris/wood%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
sound(self, CHAN_VOICE, sprintf("debris/wood%d.wav", random(1, 4)), 1.0, ATTN_NORM);
break;
case MATERIAL_METAL:
sound( self, CHAN_VOICE, sprintf( "debris/metal%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
sound(self, CHAN_VOICE, sprintf("debris/metal%d.wav", random(1, 4)), 1.0, ATTN_NORM);
break;
case MATERIAL_FLESH:
float fRand = floor( random( 1, 8 ) );
float fRand = floor(random(1, 8));
/* There never was a flesh4.wav */
if ( fRand == 4 ) {
if (fRand == 4) {
fRand = 5;
}
sound( self, CHAN_VOICE, sprintf( "debris/flesh%d.wav", fRand ), 1.0, ATTN_NORM );
sound(self, CHAN_VOICE, sprintf("debris/flesh%d.wav", fRand), 1.0, ATTN_NORM);
break;
case MATERIAL_CINDER:
case MATERIAL_ROCK:
sound( self, CHAN_VOICE, sprintf( "debris/concrete%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
sound(self, CHAN_VOICE, sprintf("debris/concrete%d.wav", random(1, 4)), 1.0, ATTN_NORM);
break;
}
}
void func_breakable :: vDeath ( entity attacker, int type, int damage )
void func_breakable::vDeath (entity attacker, int type, int damage)
{
if (m_iMaterial == MATERIAL_GLASS_UNBREAKABLE) {
return;
}
health = 0;
Effect_BreakModel( absmin, absmax, '0 0 0', m_iMaterial );
Effect_BreakModel(absmin, absmax, '0 0 0', m_iMaterial);
CBaseTrigger::UseTargets();
CBaseEntity::Hide();
}
void func_breakable :: Trigger ( void )
void func_breakable::Trigger(void)
{
func_breakable::vDeath( world, 0, 0 );
func_breakable::vDeath(world, 0, 0);
}
/*void func_breakable :: PressureDeath ( void )
/*void func_breakable::PressureDeath(void)
{
func_breakable::vDeath(m_pressAttacker, m_pressType, m_pressDamage);
}*/
void func_breakable :: PlayerTouch ( void )
void func_breakable::PlayerTouch(void)
{
if ( other.classname == classname ) {
if (other.classname == classname) {
return;
}
@ -105,7 +105,7 @@ void func_breakable :: PlayerTouch ( void )
if (fDamage >= health) {
touch = __NULL__;
Damage_Apply( this, other, fDamage, absmin, FALSE );
Damage_Apply(this, other, fDamage, absmin, FALSE);
if ((m_iMaterial == MATERIAL_GLASS) || (m_iMaterial == MATERIAL_COMPUTER)) {
Damage_Apply(other, this, fDamage / 4, other.origin, FALSE);
@ -126,14 +126,18 @@ void func_breakable :: PlayerTouch ( void )
}
void func_breakable :: Respawn ( void )
void func_breakable::Respawn(void)
{
setorigin(this, m_oldOrigin);
precache_model(m_oldModel);
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_BSP;
setmodel(this, m_oldModel);
setorigin(this, m_oldOrigin);
touch = PlayerTouch;
think = __NULL__;
if ( spawnflags & SF_TRIGGER ) {
if (spawnflags & SF_TRIGGER) {
takedamage = DAMAGE_NO;
} else {
takedamage = DAMAGE_YES;
@ -141,28 +145,23 @@ void func_breakable :: Respawn ( void )
health = m_oldHealth;
if ( !health ) {
if (!health) {
health = 15;
}
}
void func_breakable :: func_breakable( void )
void func_breakable::func_breakable(void)
{
precache_model( model );
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_BSP;
setmodel( this, model );
CBaseEntity::CBaseEntity();
func_breakable::Respawn();
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "material":
m_iMaterial = stof( argv( i + 1 ) );
m_iMaterial = stof(argv(i + 1));
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
m_flDelay = stof(argv(i + 1));
break;
default:
break;

View file

@ -25,7 +25,7 @@ enum
FRAME_ON
};
class func_button : CBaseTrigger
class func_button:CBaseTrigger
{
float m_flSpeed;
float m_flLip;
@ -39,9 +39,11 @@ class func_button : CBaseTrigger
string m_strNoise;
float m_flWait;
float m_flDelay;
vector m_vecMoveDir;
virtual void() m_pMove = 0;
virtual void() Precache;
virtual void() Respawn;
virtual void() Arrived;
virtual void() Returned;
virtual void() MoveBack;
@ -49,17 +51,17 @@ class func_button : CBaseTrigger
virtual void() Touch;
virtual void() Blocked;
virtual void() Trigger;
virtual void() PlayerUse;
virtual void() Use;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
};
void func_button :: Precache( void )
void func_button::Precache(void)
{
precache_model( model );
switch( m_iSounds ) {
precache_model(model);
switch(m_iSounds) {
case 0:
m_strNoise = "common/null.wav";
break;
@ -124,29 +126,29 @@ void func_button :: Precache( void )
m_strNoise = "buttons/button9.wav";
}
precache_sound( m_strNoise );
precache_sound(m_strNoise);
}
void func_button :: Arrived( void )
void func_button::Arrived(void)
{
m_iState = STATE_RAISED;
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
if (!(spawnflags & SF_BTT_TOUCH_ONLY)) {
touch = Touch;
}
if ( spawnflags & SF_BTT_TOGGLE ) {
if (spawnflags & SF_BTT_TOGGLE) {
return;
}
if ( m_flWait != -1 ) {
if (m_flWait != -1) {
think = MoveBack;
nextthink = ( ltime + m_flWait );
nextthink = (ltime + m_flWait);
}
}
void func_button :: Returned( void )
void func_button::Returned(void)
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
if (!(spawnflags & SF_BTT_TOUCH_ONLY)) {
touch = Touch;
}
@ -154,36 +156,36 @@ void func_button :: Returned( void )
frame = FRAME_OFF;
}
void func_button :: MoveBack( void )
void func_button::MoveBack(void)
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
if (!(spawnflags & SF_BTT_TOUCH_ONLY)) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
if ( m_vecPos2 != m_vecPos1 ) {
func_button::MoveToDestination ( m_vecPos1, Returned );
if (m_vecPos2 != m_vecPos1) {
func_button::MoveToDestination (m_vecPos1, Returned);
} else {
func_button::Returned();
}
}
void func_button :: MoveAway( void )
void func_button::MoveAway(void)
{
if ( m_iState == STATE_UP ) {
if (m_iState == STATE_UP) {
return;
}
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
if (m_iState == STATE_RAISED) {
nextthink = (ltime + m_flWait);
return;
}
m_iState = STATE_UP;
if ( m_vecPos2 != m_vecPos1 ) {
func_button::MoveToDestination( m_vecPos2, Arrived );
if (m_vecPos2 != m_vecPos1) {
func_button::MoveToDestination(m_vecPos2, Arrived);
} else {
func_button::Arrived();
}
@ -191,61 +193,61 @@ void func_button :: MoveAway( void )
frame = FRAME_ON;
}
void func_button :: Trigger( void )
void func_button::Trigger(void)
{
if ( m_flNextTrigger > time ) {
if (m_flNextTrigger > time) {
return;
}
m_flNextTrigger = time + m_flWait;
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ){
if ( m_flWait != -1 ) {
if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)){
if (m_flWait != -1) {
func_button::MoveBack();
}
return;
}
sound( this, CHAN_VOICE, m_strNoise, 1.0, ATTN_NORM );
sound(this, CHAN_VOICE, m_strNoise, 1.0, ATTN_NORM);
func_button::MoveAway();
if ( m_flDelay ) {
if (m_flDelay) {
#ifdef GS_DEVELOPER
dprint( sprintf( "func_button: Delayed trigger of `%s`\n", m_strTarget ) );
dprint(sprintf("func_button: Delayed trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
CBaseTrigger::UseTargets_Delay(m_flDelay);
} else {
#ifdef GS_DEVELOPER
print( sprintf( "func_button: Normal trigger of `%s`\n", m_strTarget ) );
print(sprintf("func_button: Normal trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets();
}
}
void func_button :: Touch( void )
void func_button::Touch(void)
{
if ( other.movetype == MOVETYPE_WALK ) {
if (other.movetype == MOVETYPE_WALK) {
func_button::Trigger();
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
if (!(spawnflags & SF_BTT_TOUCH_ONLY)) {
touch = __NULL__;
}
}
}
void func_button :: PlayerUse ( void )
void func_button::Use(void)
{
Trigger();
}
void func_button :: Blocked( void )
void func_button::Blocked(void)
{
if ( m_iDamage ) {
//Damage_Apply( other, this, dmg, other.origin, FALSE );
if (m_iDamage) {
//Damage_Apply(other, this, dmg, other.origin, FALSE);
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
if (m_flWait >= 0) {
if (m_iState == STATE_DOWN) {
func_button::MoveAway ();
} else {
func_button::MoveBack ();
@ -253,114 +255,121 @@ void func_button :: Blocked( void )
}
}
void func_button :: SetMovementDirection( void )
void func_button::SetMovementDirection(void)
{
if ( angles == '0 -1 0' ) {
movedir = '0 0 1';
} else if ( angles == '0 -2 0' ) {
movedir = '0 0 -1';
if (m_oldAngle == '0 -1 0') {
m_vecMoveDir = '0 0 1';
} else if (m_oldAngle == '0 -2 0') {
m_vecMoveDir = '0 0 -1';
} else {
makevectors( angles );
movedir = v_forward;
makevectors(m_oldAngle);
m_vecMoveDir = v_forward;
}
angles = '0 0 0';
}
void func_button :: MoveToDestination_End( void )
void func_button::MoveToDestination_End(void)
{
setorigin( this, m_vecDest );
velocity = '0 0 0';
setorigin(this, m_vecDest);
velocity = [0,0,0];
nextthink = -1;
m_pMove();
}
void func_button :: MoveToDestination( vector vDestination, void() func )
void func_button::MoveToDestination(vector vDestination, void() func)
{
vector vecDifference;
float flTravel, fTravelTime;
if ( !m_flSpeed ) {
objerror( "No speed defined for moving entity! Will not divide by zero." );
if (!m_flSpeed) {
objerror("No speed defined for moving entity! Will not divide by zero.");
}
m_pMove = func;
m_vecDest = vDestination;
think = MoveToDestination_End;
if ( vDestination == origin ) {
if (vDestination == origin) {
velocity = '0 0 0';
nextthink = ( ltime + 0.1 );
nextthink = (ltime + 0.1);
return;
}
vecDifference = ( vDestination - origin );
flTravel = vlen( vecDifference );
fTravelTime = ( flTravel / m_flSpeed );
vecDifference = (vDestination - origin);
flTravel = vlen(vecDifference);
fTravelTime = (flTravel / m_flSpeed);
if ( fTravelTime < 0.1 ) {
if (fTravelTime < 0.1) {
velocity = '0 0 0';
nextthink = ltime + 0.1;
return;
}
nextthink = ( ltime + fTravelTime );
velocity = ( vecDifference * ( 1 / fTravelTime ) );
nextthink = (ltime + fTravelTime);
velocity = (vecDifference * (1 / fTravelTime));
}
void func_button :: func_button( void )
void func_button::Respawn(void)
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
func_button::SetMovementDirection();
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, m_oldOrigin);
setmodel(this, m_oldModel);
blocked = Blocked;
velocity = [0,0,0];
nextthink = -1;
if (!m_flSpeed) {
m_flSpeed = 100;
}
if (spawnflags & SF_BTT_TOUCH_ONLY) {
touch = Touch;
PlayerUse = __NULL__;
} else {
touch = __NULL__;
PlayerUse = Use;
}
m_vecPos1 = m_oldOrigin;
if (spawnflags & SF_BTT_NOMOVE) {
m_vecPos2 = m_vecPos1;
} else {
m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip));
}
m_iState = STATE_LOWERED;
}
void func_button::func_button(void)
{
func_button::Precache();
CBaseTrigger::CBaseTrigger();
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
m_flSpeed = stof(argv(i + 1));
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
m_flLip = stof(argv(i + 1));
break;
case "sounds":
m_iSounds = stoi( argv( i + 1 ) );
m_iSounds = stoi(argv(i + 1));
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
m_flWait = stof(argv(i + 1));
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
m_flDelay = stof(argv(i + 1));
break;
default:
break;
}
}
func_button::Precache();
func_button::SetMovementDirection();
CBaseTrigger::CBaseTrigger();
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
blocked = Blocked;
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( spawnflags & SF_BTT_TOUCH_ONLY ) {
touch = Touch;
gflags -= gflags & GF_USABLE;
} else {
touch = __NULL__;
gflags |= GF_USABLE;
}
m_vecPos1 = origin;
if (spawnflags & SF_BTT_NOMOVE) {
m_vecPos2 = m_vecPos1;
} else {
m_vecPos2 = ( m_vecPos1 + movedir * ( fabs( movedir * size ) - m_flLip ) );
}
m_iState = STATE_LOWERED;
func_button::Respawn();
angles = [0,0,0];
}

View file

@ -21,7 +21,7 @@ enum
STATE_DOWN
};
class func_door : CBaseTrigger
class func_door:CBaseTrigger
{
vector m_vecPos1;
vector m_vecPos2;
@ -50,11 +50,11 @@ class func_door : CBaseTrigger
virtual void() Trigger;
virtual void() Blocked;
virtual void() Touch;
virtual void() PlayerUse;
virtual void() Use;
virtual void() m_pMove = 0;
};
void func_door :: Precache (void)
void func_door::Precache(void)
{
if(m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
precache_sound(sprintf("doors/doormove%i.wav", m_iMoveSnd));
@ -69,13 +69,13 @@ void func_door :: Precache (void)
}
}
void func_door :: PlayerUse (void)
void func_door::Use(void)
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
}
void func_door :: Arrived (void)
void func_door::Arrived(void)
{
m_iState = STATE_RAISED;
@ -98,7 +98,7 @@ void func_door :: Arrived (void)
}
}
void func_door :: Returned (void)
void func_door::Returned(void)
{
if(m_iStopSnd > 0 && m_iStopSnd <= 8) {
sound(self, CHAN_VOICE, sprintf("doors/doorstop%i.wav", m_iStopSnd), 1.0, ATTN_NORM);
@ -113,7 +113,7 @@ void func_door :: Returned (void)
m_iState = STATE_LOWERED;
}
void func_door :: MoveBack (void)
void func_door::MoveBack(void)
{
if(m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
sound(self, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM);
@ -129,7 +129,7 @@ void func_door :: MoveBack (void)
MoveToDestination(m_vecPos1, Returned);
}
void func_door :: MoveAway (void)
void func_door::MoveAway(void)
{
if (m_iState == STATE_UP) {
return;
@ -152,7 +152,7 @@ void func_door :: MoveAway (void)
MoveToDestination(m_vecPos2, Arrived);
}
void func_door :: Trigger (void)
void func_door::Trigger(void)
{
if (m_flNextTrigger > ltime) {
if (!(spawnflags & SF_MOV_TOGGLE)) {
@ -184,7 +184,7 @@ void func_door :: Trigger (void)
MoveAway();
}
void func_door :: Touch (void)
void func_door::Touch(void)
{
if (spawnflags & SF_MOV_TOGGLE) {
return;
@ -201,7 +201,7 @@ void func_door :: Touch (void)
}
}
void func_door :: Blocked (void)
void func_door::Blocked(void)
{
if(m_iDamage) {
//Damage_Apply(other, self, dmg, other.origin, FALSE);
@ -216,13 +216,69 @@ void func_door :: Blocked (void)
}
}
void func_door :: Respawn (void)
void func_door::SetMovementDirection(void)
{
if (angles == [0,-1,0]) {
m_vecMoveDir = [0,0,1];
} else if (angles == [0,-2,0]) {
m_vecMoveDir = [0,0,-1];
} else {
makevectors(angles);
m_vecMoveDir = v_forward;
}
}
void func_door::MoveToDestination_End(void)
{
setorigin(this, m_vecDest);
velocity = [0,0,0];
nextthink = -1;
m_pMove();
}
void func_door::MoveToDestination(vector vDestination, void() func)
{
vector vecDifference;
float flTravel;
float fTravelTime;
if (!m_flSpeed) {
objerror("func_door: No speed defined!");
return;
}
m_pMove = func;
m_vecDest = vDestination;
think = MoveToDestination_End;
if (vDestination == origin) {
velocity = [0,0,0];
nextthink = (ltime + 0.1f);
return;
}
vecDifference = (vDestination - origin);
flTravel = vlen(vecDifference);
fTravelTime = (flTravel / m_flSpeed);
if (fTravelTime < 0.1) {
velocity = [0,0,0];
nextthink = ltime + 0.1f;
return;
}
nextthink = (ltime + fTravelTime);
velocity = (vecDifference * (1 / fTravelTime));
}
void func_door::Respawn(void)
{
func_door::SetMovementDirection();
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
setorigin(this, m_oldOrigin);
setmodel(this, m_oldModel);
blocked = Blocked;
//Use = Trigger;
@ -241,81 +297,24 @@ void func_door :: Respawn (void)
if (spawnflags & SF_MOV_USE) {
touch = __NULL__;
gflags |= GF_USABLE;
PlayerUse = Use;
} else {
touch = Touch;
gflags -= gflags & GF_USABLE;
PlayerUse = __NULL__;
}
m_iState = STATE_LOWERED;
m_vecPos1 = origin;
m_vecPos1 = m_oldOrigin;
m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip));
if (spawnflags & SF_MOV_OPEN) {
setorigin(this, m_vecPos2);
m_vecPos2 = m_vecPos1;
m_vecPos1 = origin;
m_vecPos1 = m_oldOrigin;
}
}
void func_door :: SetMovementDirection (void)
{
if (angles == [0,-1,0]) {
m_vecMoveDir = [0,0,1];
} else if (angles == [0,-2,0]) {
m_vecMoveDir = [0,0,-1];
} else {
makevectors(angles);
m_vecMoveDir = v_forward;
}
angles = [0,0,0];
}
void func_door :: MoveToDestination_End (void)
{
setorigin(this, m_vecDest);
velocity = [0,0,0];
nextthink = -1;
m_pMove();
}
void func_door :: MoveToDestination (vector vDestination, void() func)
{
vector vecDifference;
float flTravel;
float fTravelTime;
if (!m_flSpeed) {
objerror("func_door: No speed defined!");
return;
}
m_pMove = func;
m_vecDest = vDestination;
think = MoveToDestination_End;
if (vDestination == origin) {
velocity = '0 0 0';
nextthink = (ltime + 0.1);
return;
}
vecDifference = (vDestination - origin);
flTravel = vlen(vecDifference);
fTravelTime = (flTravel / m_flSpeed);
if (fTravelTime < 0.1) {
velocity = '0 0 0';
nextthink = ltime + 0.1;
return;
}
nextthink = (ltime + fTravelTime);
velocity = (vecDifference * (1 / fTravelTime));
}
void func_door :: func_door (void)
void func_door::func_door(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
@ -342,10 +341,11 @@ void func_door :: func_door (void)
}
}
func_door::Precache();
func_door::SetMovementDirection();
func_door::Respawn();
CBaseTrigger::CBaseTrigger();
func_door::Precache();
func_door::Respawn();
angles = [0,0,0];
if (m_strTargetName) {
m_iLocked = TRUE;

View file

@ -37,32 +37,33 @@ class func_door_rotating:CBaseTrigger
virtual void() m_pMove = 0;
void() func_door_rotating;
virtual void() Respawn;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() RotateBack;
virtual void() RotateAway;
virtual void() Trigger;
virtual void() PlayerUse;
virtual void() Use;
virtual void() Touch;
virtual void() Blocked;
virtual void() SetMovementDirection;
virtual void( vector angle, void() func ) RotateToDestination;
virtual void(vector angle, void() func) RotateToDestination;
virtual void() RotateToDestination_End;
};
void func_door_rotating::Precache(void)
{
if ( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
precache_sound( sprintf( "doors/doormove%i.wav", m_iMoveSnd ) );
if (m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
precache_sound(sprintf("doors/doormove%i.wav", m_iMoveSnd));
} else {
precache_sound( "common/null.wav" );
precache_sound("common/null.wav");
}
if ( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
precache_sound( sprintf( "doors/doorstop%i.wav", m_iStopSnd ) );
if (m_iStopSnd > 0 && m_iStopSnd <= 8) {
precache_sound(sprintf("doors/doorstop%i.wav", m_iStopSnd));
} else {
precache_sound( "common/null.wav" );
precache_sound("common/null.wav");
}
}
@ -70,26 +71,26 @@ void func_door_rotating::Arrived(void)
{
m_iState = STATE_RAISED;
if ( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
sound( this, CHAN_VOICE, sprintf( "doors/doorstop%i.wav", m_iStopSnd ), 1.0, ATTN_NORM );
if (m_iStopSnd > 0 && m_iStopSnd <= 8) {
sound(this, CHAN_VOICE, sprintf("doors/doorstop%i.wav", m_iStopSnd), 1.0, ATTN_NORM);
} else {
sound( this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if ( !(spawnflags & SF_ROT_USE) ) {
if (!(spawnflags & SF_ROT_USE)) {
touch = Touch;
}
if ( m_flWait < 0 ) {
if (m_flWait < 0) {
return;
}
think = RotateBack;
nextthink = ( ltime + m_flWait );
nextthink = (ltime + m_flWait);
}
void func_door_rotating::Returned(void)
{
if ( !(spawnflags & SF_ROT_USE) ) {
if (!(spawnflags & SF_ROT_USE)) {
touch = Touch;
}
@ -98,84 +99,84 @@ void func_door_rotating::Returned(void)
void func_door_rotating::RotateBack(void)
{
if ( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( this, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
if (m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
sound(this, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM);
} else {
sound( this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if ( !(spawnflags & SF_ROT_USE) ) {
if (!(spawnflags & SF_ROT_USE)) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
RotateToDestination( m_vecPos1, Returned );
RotateToDestination(m_vecPos1, Returned);
}
void func_door_rotating::RotateAway(void)
{
float fDirection = 1.0;
if ( m_iState == STATE_UP ) {
if (m_iState == STATE_UP) {
return;
}
if ( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( this, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
if (m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
sound(this, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM);
} else {
sound( this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
if (m_iState == STATE_RAISED) {
nextthink = (ltime + m_flWait);
return;
}
m_iState = STATE_UP;
if ( !( spawnflags & SF_ROT_ONEWAY ) ) {
if (!(spawnflags & SF_ROT_ONEWAY)) {
vector vDifference = eActivator.origin - origin;
vector vAngles = eActivator.angles;
vAngles[0] = vAngles[2] = 0;
makevectors( vAngles );
vector vNext = ( eActivator.origin + ( v_forward * 10 ) ) - origin;
makevectors(vAngles);
vector vNext = (eActivator.origin + (v_forward * 10)) - origin;
if ( ( ( vDifference[0] * vNext[1] ) - ( vDifference[1] * vNext[0] ) ) < 0 ) {
if (((vDifference[0] * vNext[1]) - (vDifference[1] * vNext[0])) < 0) {
fDirection = -1.0f;
}
}
RotateToDestination( m_vecPos2 * fDirection, Arrived );
RotateToDestination(m_vecPos2 * fDirection, Arrived);
}
void func_door_rotating::Trigger(void)
{
if ( m_flNextAction > time ) {
if (m_flNextAction > time) {
return;
}
m_flNextAction = time + m_flWait;
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ) {
if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)) {
RotateBack();
return;
}
RotateAway();
if ( m_flDelay ) {
if (m_flDelay) {
#ifdef GS_DEVELOPER
print( sprintf( "func_door_rotating: Delayed trigger of `%s`\n", m_strTarget ) );
print(sprintf("func_door_rotating: Delayed trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
CBaseTrigger::UseTargets_Delay(m_flDelay);
} else {
#ifdef GS_DEVELOPER
print( sprintf( "func_door_rotating: Normal trigger of `%s`\n", m_strTarget ) );
print(sprintf("func_door_rotating: Normal trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets();
}
}
void func_door_rotating::PlayerUse(void)
void func_door_rotating::Use(void)
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
@ -183,12 +184,12 @@ void func_door_rotating::PlayerUse(void)
void func_door_rotating::Touch(void)
{
if ( spawnflags & SF_ROT_USE ) {
if (spawnflags & SF_ROT_USE) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin[2] <= maxs[2] - 2 ) {
if (other.movetype == MOVETYPE_WALK) {
if (other.absmin[2] <= maxs[2] - 2) {
eActivator = other;
Trigger();
}
@ -198,69 +199,34 @@ void func_door_rotating::Touch(void)
void func_door_rotating::Blocked(void)
{
if ( m_iDamage ) {
Damage_Apply( other, this, m_iDamage, other.origin, FALSE );
if (m_iDamage) {
Damage_Apply(other, this, m_iDamage, other.origin, FALSE);
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
RotateAway ();
if (m_flWait >= 0) {
if (m_iState == STATE_DOWN) {
RotateAway();
} else {
RotateBack ();
RotateBack();
}
}
}
void func_door_rotating::Respawn(void)
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
blocked = Blocked;
use = Trigger;
if ( spawnflags & SF_ROT_USE ) {
touch = __NULL__;
gflags |= GF_USABLE;
} else {
touch = Touch;
gflags -= gflags & GF_USABLE;
}
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
m_iState = STATE_LOWERED;
m_vecPos1 = angles;
m_vecPos2 = angles + m_vecMoveDir * m_flDistance;
if ( spawnflags & SF_ROT_OPEN ) {
vector vTemp = m_vecPos2;
m_vecPos2 = m_vecPos1;
m_vecPos1 = vTemp;
angles = m_vecPos1;
movedir = movedir * -1;
}
}
void func_door_rotating::SetMovementDirection(void)
{
if ( spawnflags & SF_ROT_ZAXIS ) {
m_vecMoveDir = '0 0 1';
} else if ( spawnflags & SF_ROT_XAXIS ) {
m_vecMoveDir = '1 0 0';
if (spawnflags & SF_ROT_ZAXIS) {
m_vecMoveDir = [0,0,1];
} else if (spawnflags & SF_ROT_XAXIS) {
m_vecMoveDir = [1,0,0];
} else {
m_vecMoveDir = '0 1 0';
m_vecMoveDir = [0,1,0];
}
}
void func_door_rotating::RotateToDestination_End(void)
{
angles = m_vecDest;
avelocity = '0 0 0';
avelocity = [0,0,0];
nextthink = -1;
m_pMove();
}
@ -270,61 +236,100 @@ void func_door_rotating::RotateToDestination(vector vDestinationAngle, void() fu
vector vecAngleDifference;
float flTravelLength, flTravelTime;
if ( !m_flSpeed ) {
objerror( "No speed defined for moving entity! Will not divide by zero." );
if (!m_flSpeed) {
objerror("No speed defined for moving entity! Will not divide by zero.");
}
vecAngleDifference = ( vDestinationAngle - angles );
flTravelLength = vlen( vecAngleDifference );
flTravelTime = ( flTravelLength / m_flSpeed );
avelocity = ( vecAngleDifference * ( 1 / flTravelTime ) );
vecAngleDifference = (vDestinationAngle - angles);
flTravelLength = vlen(vecAngleDifference);
flTravelTime = (flTravelLength / m_flSpeed);
avelocity = (vecAngleDifference * (1 / flTravelTime));
m_vecDest = vDestinationAngle;
m_pMove = func;
think = RotateToDestination_End;
nextthink = ( ltime + flTravelTime );
nextthink = (ltime + flTravelTime);
}
void func_door_rotating::Respawn(void)
{
func_door_rotating::SetMovementDirection();
if (!m_flSpeed) {
m_flSpeed = 100;
}
if (!m_flLip) {
m_flLip = 90;
}
if (!m_flDelay) {
m_flDelay = 4;
}
if (!m_flDistance) {
m_flDistance = 90;
}
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, m_oldOrigin);
setmodel(this, m_oldModel);
think = __NULL__;
nextthink = -1;
m_pMove = 0;
avelocity = [0,0,0];
blocked = Blocked;
if (spawnflags & SF_ROT_USE) {
touch = __NULL__;
PlayerUse = Use;
} else {
touch = Touch;
PlayerUse = __NULL__;
}
m_iState = STATE_LOWERED;
m_vecPos1 = m_oldAngle;
m_vecPos2 = m_oldAngle + m_vecMoveDir * m_flDistance;
if (spawnflags & SF_ROT_OPEN) {
vector vTemp = m_vecPos2;
m_vecPos2 = m_vecPos1;
m_vecPos1 = vTemp;
//m_vecMoveDir = m_vecMoveDir * -1;
}
angles = m_vecPos1;
}
void func_door_rotating::func_door_rotating(void)
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
m_flSpeed = stof(argv(i+1));
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
m_flLip = stof(argv(i+1));
break;
case "movesnd":
m_iMoveSnd = stoi( argv( i + 1 ) );
m_iMoveSnd = stoi(argv(i+1));
break;
case "stopsnd":
m_iStopSnd = stoi( argv( i + 1 ) );
m_iStopSnd = stoi(argv(i+1));
break;
case "distance":
m_flDistance = stof( argv( i + 1 ) );
m_flDistance = stof(argv(i+1));
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
m_flDelay = stof(argv(i+1));
break;
case "dmg":
m_iDamage = stoi(argv(i+1));
break;
default:
break;
}
}
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( !m_flLip ) {
m_flLip = 90;
}
if ( !m_flDelay ) {
m_flDelay = 4;
}
if ( !m_flDistance ) {
m_flDistance = 90;
}
func_door_rotating::Precache();
CBaseEntity::CBaseEntity();
func_door_rotating::SetMovementDirection();
func_door_rotating::Respawn();
}

View file

@ -16,7 +16,7 @@ class func_healthcharger:CBaseTrigger
void func_healthcharger::PlayerUse(void)
{
eActivator.flags = (eActivator.flags - FL_USERELEASED);
eActivator.gflags &= ~GF_USE_RELEASED;
if (m_flDelay > time) {
return;
@ -32,5 +32,4 @@ void func_healthcharger::func_healthcharger(void)
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
gflags = GF_USABLE;
}

View file

@ -16,7 +16,7 @@ class func_recharge:CBaseTrigger
void func_recharge::PlayerUse(void)
{
eActivator.flags = (eActivator.flags - FL_USERELEASED);
eActivator.gflags &= ~GF_USE_RELEASED;
if (m_flDelay > time) {
return;
@ -32,5 +32,4 @@ void func_recharge::func_recharge(void)
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
gflags = GF_USABLE;
}

Binary file not shown.

View file

@ -0,0 +1,36 @@
!!ver 100-450
!!samps 1
!!cvardf gl_fake16bit=0
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.
//its really not meant to do anything special.
varying vec2 tc;
varying vec4 vc;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
attribute vec4 v_colour;
void main ()
{
tc = v_texcoord;
vc = v_colour;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
void main ()
{
vec4 f = vc;
#ifdef PREMUL
f.rgb *= f.a;
#endif
f *= texture2D(s_t0, tc);
#if gl_fake16bit == 1
f.rgb = floor(f.rgb * vec3(32,64,32))/vec3(32,64,32);
#endif
gl_FragColor = f;
}
#endif

View file

@ -0,0 +1,21 @@
!!ver 100-450
!!cvardf gl_fake16bit=0
#ifdef VERTEX_SHADER
attribute vec4 v_colour;
varying vec4 vc;
void main ()
{
vc = v_colour;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
varying vec4 vc;
void main ()
{
gl_FragColor = vc;
}
#endif

View file

@ -1,27 +1,45 @@
!!ver 120
!!ver 130
!!permu FRAMEBLEND
!!permu SKELETAL
!!permu FOG
!!samps diffuse
!!cvardf gl_affinemodels=0
!!cvardf gl_fake16bit=0
#include "sys/defs.h"
varying vec2 tex_c;
#if gl_affinemodels == 1
#define affine noperspective
#else
#define affine
#endif
affine varying vec2 tex_c;
varying vec3 light;
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
float hl( vec3 normal, vec3 dir ) {
/*float hl( vec3 normal, vec3 dir ) {
return ( dot( normal, dir ) * 0.5 ) + 0.5;
}
}*/
void main ()
{
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
tex_c = v_texcoord;
light = e_light_ambient + ( e_light_mul * hl( n, e_light_dir ) );
light = e_light_ambient + ( e_light_mul * dot( n, e_light_dir ) );
if (light.r > 1.0f) {
light.r = 1.0f;
}
if (light.g > 1.0f) {
light.g = 1.0f;
}
if (light.b > 1.0f) {
light.b = 1.0f;
}
}
#endif
@ -29,8 +47,12 @@ varying vec3 light;
#ifdef FRAGMENT_SHADER
void main ()
{
vec4 diffuse_f = texture2D( s_diffuse, tex_c );
vec4 diffuse_f = texture2D(s_diffuse, tex_c);
diffuse_f.rgb *= light;
diffuse_f *= e_colourident;
#if gl_fake16bit == 1
diffuse_f.rgb = floor(diffuse_f.rgb * vec3(32,64,32))/vec3(32,64,32);
#endif
gl_FragColor = diffuse_f * e_colourident;
}
#endif

View file

@ -1,6 +1,7 @@
!!ver 110
!!permu FOG
!!samps reflectcube
!!cvardf gl_fake16bit=0
#include "sys/defs.h"
#include "sys/fog.h"
@ -18,6 +19,9 @@ void main ()
void main ()
{
vec4 skybox = textureCube(s_reflectcube, pos);
#if gl_fake16bit == 1
skybox.rgb = floor(skybox.rgb * vec3(32,64,32))/vec3(32,64,32);
#endif
gl_FragColor = vec4(fog3(skybox.rgb), 1.0);
}
#endif

View file

@ -0,0 +1,42 @@
!!permu FOG
!!samps 1
!!cvardf gl_fake16bit=0
//used by both particles and sprites.
//note the fog blending mode is all that differs from defaultadditivesprite
#include "sys/fog.h"
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
attribute vec4 v_colour;
varying vec2 tc;
varying vec4 vc;
void main ()
{
tc = v_texcoord;
vc = v_colour;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 tc;
varying vec4 vc;
uniform vec4 e_colourident;
uniform vec4 e_vlscale;
void main ()
{
vec4 col = texture2D(s_t0, tc);
#ifdef MASK
if (col.a < float(MASK))
discard;
#endif
col = fog4blend(col * vc * e_colourident * e_vlscale);
#if gl_fake16bit == 1
col.rgb = floor(col.rgb * vec3(32,64,32))/vec3(32,64,32);
#endif
gl_FragColor = col;
}
#endif

View file

@ -1,5 +1,6 @@
!!ver 110
!!samps diffuse lightmap
!!cvardf gl_fake16bit=0
#include "sys/defs.h"
@ -18,15 +19,29 @@ varying vec2 lm_c;
#ifdef FRAGMENT_SHADER
void main ( void )
{
vec4 diffuse_f = texture2D( s_diffuse, tex_c );
vec4 diffuse_f = texture2D(s_diffuse, tex_c);
vec3 light = texture2D(s_lightmap, lm_c).rgb;
if (light.r > 1.0f) {
light.r = 1.0f;
}
if (light.g > 1.0f) {
light.g = 1.0f;
}
if (light.b > 1.0f) {
light.b = 1.0f;
}
if ( diffuse_f.a < 0.5 ) {
if (diffuse_f.a < 0.5) {
discard;
}
diffuse_f.rgb *= texture2D( s_lightmap, lm_c ).rgb * e_lmscale.rgb;
diffuse_f.rgb *= light.rgb;
diffuse_f *= e_colourident;
#if gl_fake16bit == 1
diffuse_f.rgb = floor(diffuse_f.rgb * vec3(32,64,32))/vec3(32,64,32);
#endif
gl_FragColor = diffuse_f;
}
#endif

Binary file not shown.

Binary file not shown.