Implemented env_render, cycler_sprite, trigger_multiple and a few other bits

This commit is contained in:
Marco Hladik 2016-12-04 02:27:15 +01:00
parent a75b6d1dda
commit dac1623b0d
12 changed files with 361 additions and 2305 deletions

View file

@ -155,6 +155,20 @@ enum {
EV_MODELGIB,
};
// Submodel materials
enum {
MATERIAL_GLASS = 0,
MATERIAL_WOOD,
MATERIAL_METAL,
MATERIAL_FLESH,
MATERIAL_CINDER,
MATERIAL_TILE,
MATERIAL_COMPUTER,
MATERIAL_GLASS_UNBREAKABLE,
MATERIAL_ROCK,
MATERIAL_NONE
};
float clamp(float d, float imin, float imax) {
float t;

View file

@ -0,0 +1,47 @@
/*
OpenCS Project
Copyright (C) 2015 Marco "eukara" Hladik
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void ambient_generic_use( void ) {
sound( self, CHAN_VOICE, self.message, 1, self.style );
}
void ambient_generic( void ) {
precache_sound( self.message );
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 ) {
sound( self, CHAN_VOICE, self.message, 1, self.style );
} else {
ambientsound( self.origin, self.message, 1, self.style );
}
self.vUse = ambient_generic_use;
}

View file

@ -18,9 +18,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void Damage_Apply( entity eTarget, entity eAttacker, float fWeapon, vector vHitPos ) {
void Damage_Apply( entity eTarget, entity eAttacker, int iDamage, vector vHitPos ) {
eTarget.health = eTarget.health - wptTable[ self.weapon ].iDamage; // TODO: Body part multipliers
eTarget.health = eTarget.health - iDamage; // TODO: Body part multipliers
if ( eTarget.iBleeds == TRUE ) {
makevectors( eAttacker.angles );

View file

@ -88,3 +88,6 @@ float OpenCSGunBase_PrimaryFire( void );
float OpenCSGunBase_Reload( void );
void TraceAttack_FireBullets( int iShots );
// WIP
string __fullspawndata;

View file

@ -18,20 +18,54 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void Entities_UseTargets( void ) {
entity eFind = findchain( targetname, self.target );
while ( eFind ) {
entity eOldSelf = self;
self = eFind;
eFind.vUse();
self = eOldSelf;
eFind = eFind.chain;
}
}
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 );
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_FULLBRIGHT;
}
}
}
void func_wall( void ) {
static void func_wall_use( void ) {
self.skin = 1 - self.skin;
}
self.angles = '0 0 0';
self.movetype = MOVETYPE_PUSH;
self.solid = SOLID_BSP;
setmodel (self, self.model);
// GoldSrc-Rendermode support
if( self.rendermode == 2 ) {
self.alpha = ( self.renderamt / 255 );
} else if ( self.rendermode == 5 ) {
self.effects = EF_ADDITIVE;
self.alpha = ( self.renderamt / 255 );
}
setmodel( self, self.model );
self.vUse = func_wall_use;
Entities_RenderSetup();
}
void func_door( void ) {
@ -51,21 +85,3 @@ void func_water( void ) {
func_wall();
self.skin = CONTENT_WATER;
}
void ambient_generic( void ) {
precache_sound( self.message );
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;
}
ambientsound( self.origin, self.message, 1, self.style );
}

View file

@ -0,0 +1,48 @@
/*
OpenCS Project
Copyright (C) 2015 Marco "eukara" Hladik
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void cycler_sprite( void ) {
static void cycler_sprite_use( void ) {
remove( self );
}
precache_model( self.model );
setmodel( self, self.model );
self.vUse = cycler_sprite_use;
Entities_RenderSetup();
}
void env_render( void ) {
static void env_render_use( void ) {
entity eFind = findchain( targetname, self.target );
while ( eFind ) {
entity eOldSelf = self;
eFind.rendermode = self.rendermode;
eFind.rendercolor = self.rendercolor;
eFind.alpha = self.alpha;
eFind = eFind.chain;
}
}
Entities_RenderSetup();
self.vUse = env_render_use;
}

View file

@ -20,21 +20,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// 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
// These are the material types apparently
.float material;
enum {
MATERIAL_GLASS = 0,
MATERIAL_WOOD,
MATERIAL_METAL,
MATERIAL_FLESH,
MATERIAL_CINDER,
MATERIAL_TILE,
MATERIAL_COMPUTER,
MATERIAL_GLASS_UNBREAKABLE,
MATERIAL_ROCK,
MATERIAL_NONE
};
// Whenever it gets damaged
void func_breakable_pain( void ) {
@ -111,11 +111,44 @@ void func_breakable_die( void ) {
sound( self, CHAN_VOICE, sprintf( "%s%d.wav", sTypeSample, ceil( random() * iTypeCount ) ), 1.0, ATTN_NORM );
}
Effect_BreakModel( self.origin, self.size, self.velocity, self.style );
Effect_BreakModel( self.absmin, self.absmax, self.velocity, self.material );
Entities_UseTargets();
remove( self );
}
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.01);
if ( fDamage >= self.health ) {
self.touch = func_breakable_touch_NULL;
Damage_Apply( self, other, fDamage, self.absmin );
if ( self.material == MATERIAL_GLASS || self.material == MATERIAL_COMPUTER ) {
Damage_Apply( other, self, fDamage/4, other.origin );
}
}
}
if ( ( self.spawnflags & SF_PRESSURE ) && other.absmin_z >= self.maxs_z - 2 ) {
self.think = func_breakable_die;
if ( self.delay == 0 ) {
self.delay = 0.1;
}
self.nextthink = self.ltime + self.delay;
}
}
/*
=================
SPAWN: func_breakable
@ -125,8 +158,19 @@ Entry function for the brushes that can die etc.
*/
void func_breakable( void ) {
func_wall();
self.vPain = func_breakable_pain;
self.vDeath = func_breakable_die;
self.iBleeds = FALSE;
self.takedamage = DAMAGE_YES;
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_die;
}

View file

@ -31,7 +31,7 @@ void TraceAttack_FireBullets( int iShots ) {
traceline( vSrc, vSrc + ( vDir * 2048 ), FALSE, self);
if (trace_fraction != 1.0) {
if ( trace_ent.takedamage == DAMAGE_YES ) {
Damage_Apply( trace_ent, self, self.weapon, trace_endpos );
Damage_Apply( trace_ent, self, wptTable[ self.weapon ].iDamage, trace_endpos );
} else {
pointparticles( EFFECT_GUNSHOT, trace_endpos, '0 0 0', 1 );
}

79
Source/Server/Triggers.c Normal file
View file

@ -0,0 +1,79 @@
/*
TRIGGER_MULTIPLE
http://twhl.info/wiki.php?id=139
Target (target) - When an entity is activated, it triggers the entity with the name specified by Target.
Name (targetname) - Property used to identify entities.
Master (master) - The name of a multisource (or game_team_master) entity. A master must usually be active in order for the entity to work. Thus they act almost like an on/off switch, in their simplest form, and like an AND gate in the case of the multisource.
Delay before trigger (delay) - Usually the time in seconds before an entity should trigger its target (after being triggered itself). Under other SmartEdit names, delay might also be the time to wait before performing some other action.
Kill target (killtarget) - Remove this entity from the game when triggered
Target Path (netname)
Sound style (sounds)
Message (message)
Delay before reset (wait) - Time in seconds before the entity is ready to be re-triggered.
*/
// This is what they use...
.string killtarget;
.float wait;
.float delay;
void trigger_multiple_trigger( void ) {
Entities_UseTargets();
if ( self.killtarget ) {
entity eFind = findchain( killtarget, self.target );
while ( eFind ) {
entity eRemoveMe = eFind;
remove( eRemoveMe );
eFind = eFind.chain;
}
}
}
/*
=================
SPAWN: trigger_multiple
Entry function for this nice trigger object.
=================
*/
void trigger_multiple( void ) {
static void trigger_multiple_use( void ) {
if ( self.delay ) {
self.think = trigger_multiple_trigger;
self.nextthink = self.ltime + self.delay;
} else {
trigger_multiple_trigger();
}
}
static void trigger_multiple_touch( void ) {
if ( self.fAttackFinished > self.ltime ) {
return;
}
if ( other.classname == "player" ) {
trigger_multiple_use();
self.fAttackFinished = self.ltime + self.wait;
}
}
self.angles = '0 0 0';
self.solid = SOLID_TRIGGER;
setmodel( self, self.model );
self.model = 0;
self.vUse = trigger_multiple_use;
self.touch = trigger_multiple_touch;
}
void multi_manager( void ) {
static void multi_manager_use( void ) {
eprint( self );
}
self.message = __fullspawndata;
self.think = multi_manager_use;
self.nextthink = self.ltime + 5;
}

File diff suppressed because it is too large Load diff

View file

@ -40,6 +40,9 @@ Timer.c
Main.c
EntHostage.c
Entities.c
Triggers.c
AmbientSound.c
EnvObjects.c
FuncBreakable.c
FuncLadder.c
FuncHostageRescue.c

View file

@ -18,34 +18,80 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void Effect_BreakModel( vector vPos, vector vSize, vector vVel, float fStyle ) {
void Effect_BreakModel( vector vMins, vector vMaxs, vector vVel, float fStyle ) {
#ifdef SSQC
WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET );
WriteByte( MSG_MULTICAST, EV_MODELGIB );
WriteCoord( MSG_MULTICAST, vPos_x);
WriteCoord( MSG_MULTICAST, vPos_y);
WriteCoord( MSG_MULTICAST, vPos_z);
WriteCoord( MSG_MULTICAST, vSize_x);
WriteCoord( MSG_MULTICAST, vSize_y);
WriteCoord( MSG_MULTICAST, vSize_z);
WriteCoord( MSG_MULTICAST, vMins_x);
WriteCoord( MSG_MULTICAST, vMins_y);
WriteCoord( MSG_MULTICAST, vMins_z);
WriteCoord( MSG_MULTICAST, vMaxs_x);
WriteCoord( MSG_MULTICAST, vMaxs_y);
WriteCoord( MSG_MULTICAST, vMaxs_z);
WriteByte( MSG_MULTICAST, fStyle );
msg_entity = self;
multicast( '0 0 0', MULTICAST_PVS );
#else
static void Effect_BreakModel_Remove( void ) { remove( self ) ; }
float fCount = 20; // TODO: Generate gibcount based around size.
vector vRandPos;
vector vPos;
string sModel = "";
switch ( fStyle ) {
case MATERIAL_GLASS:
case MATERIAL_GLASS_UNBREAKABLE:
sModel = "models/glassgibs.mdl";
break;
case MATERIAL_WOOD:
sModel = "models/woodgibs.mdl";
break;
case MATERIAL_METAL:
sModel = "models/metalplategibs.mdl";
break;
case MATERIAL_FLESH:
sModel = "models/fleshgibs.mdl";;
break;
case MATERIAL_CINDER:
sModel = "models/cindergibs.mdl";
break;
case MATERIAL_TILE:
sModel = "models/ceilinggibs.mdl";
break;
case MATERIAL_COMPUTER:
sModel = "models/computergibs.mdl";
break;
case MATERIAL_ROCK:
sModel = "models/rockgibs.mdl";
break;
default:
sModel = "models/cindergibs.mdl";
}
while ( fCount > 0 ) {
entity eGib = spawn();
vRandPos_x = random() * vSize_x;
vRandPos_y = random() * vSize_y;
vRandPos_z = random() * vSize_z;
vRandPos = vRandPos - ( vSize / 2 );
vPos_x = vMins_x + ( random() * ( vMaxs_x - vMins_x ) );
vPos_y = vMins_y + ( random() * ( vMaxs_y - vMins_y ) );
vPos_z = vMins_z + ( random() * ( vMaxs_z - vMins_z ) );
setorigin( eGib, vPos );
setmodel( eGib, sModel ); // Placeholder
eGib.movetype = MOVETYPE_BOUNCE;
eGib.solid = SOLID_NOT;
eGib.avelocity_x = random()*600;
eGib.avelocity_y = random()*600;
eGib.avelocity_z = random()*600;
eGib.think = Effect_BreakModel_Remove;
eGib.nextthink = time + 10;
if ( ( fStyle == MATERIAL_GLASS ) || ( fStyle == MATERIAL_GLASS_UNBREAKABLE ) ) {
eGib.effects = EF_ADDITIVE;
eGib.alpha = 0.3;
}
setorigin( eGib, vPos + vRandPos );
setmodel( eGib, "models/head.mdl" ); // Placeholder
fCount--;
eGib.drawmask = MASK_ENGINE;
}