Switched the majority of entities over to my new object oriented entity codebase also featured in The Wastes 1.2

This commit is contained in:
Marco Cawthorne 2018-12-31 02:00:38 +01:00
parent 88710b3bb2
commit 07b72429f6
77 changed files with 4674 additions and 143 deletions

View file

@ -24,36 +24,43 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
var string autocvar_skins_dir = "";
string sViewModels[ CS_WEAPON_COUNT - 1 ] = {
"models/v_knife.mdl",
"models/v_usp.mdl",
"models/v_glock18.mdl",
"models/v_deagle.mdl",
"models/v_p228.mdl",
"models/v_elite.mdl",
"models/v_fiveseven.mdl",
"models/v_m3.mdl",
"models/v_xm1014.mdl",
"models/v_mp5.mdl",
"models/v_p90.mdl",
"models/v_ump45.mdl",
"models/v_mac10.mdl",
"models/v_tmp.mdl",
"models/v_ak47.mdl",
"models/v_sg552.mdl",
"models/v_m4a1.mdl",
"models/v_aug.mdl",
"models/v_scout.mdl",
"models/v_awp.mdl",
"models/v_g3sg1.mdl",
"models/v_sg550.mdl",
"models/v_m249.mdl",
"models/v_c4.mdl",
"models/v_flashbang.mdl",
"models/v_hegrenade.mdl",
"models/v_smokegrenade.mdl"
"v_knife.mdl",
"v_usp.mdl",
"v_glock18.mdl",
"v_deagle.mdl",
"v_p228.mdl",
"v_elite.mdl",
"v_fiveseven.mdl",
"v_m3.mdl",
"v_xm1014.mdl",
"v_mp5.mdl",
"v_p90.mdl",
"v_ump45.mdl",
"v_mac10.mdl",
"v_tmp.mdl",
"v_ak47.mdl",
"v_sg552.mdl",
"v_m4a1.mdl",
"v_aug.mdl",
"v_scout.mdl",
"v_awp.mdl",
"v_g3sg1.mdl",
"v_sg550.mdl",
"v_m249.mdl",
"v_c4.mdl",
"v_flashbang.mdl",
"v_hegrenade.mdl",
"v_smokegrenade.mdl"
};
void View_Init(void)
{
}
/*
====================
View_CalcBob
@ -210,7 +217,13 @@ void View_DrawViewModel( void ) {
if ( pSeat->fLastWeapon != aw ) {
pSeat->fLastWeapon = aw;
if ( aw >= 1 ) {
setmodel( eViewModel, sViewModels[ aw - 1 ] );
string wm;
if (autocvar_skins_dir != "") {
wm = sprintf("skins/%s/%s", autocvar_skins_dir, sViewModels[ aw - 1 ]);
} else {
wm = sprintf("models/%s", sViewModels[ aw - 1 ]);
}
setmodel( eViewModel, wm );
skel_delete( eMuzzleflash.skeletonindex );
eMuzzleflash.skeletonindex = skel_create( eViewModel.modelindex );
pSeat->fNumBones = skel_get_numbones( eMuzzleflash.skeletonindex ) + 1;

View file

@ -20,6 +20,9 @@ void create_btnok_start(void)
{
static string startmap;
static void create_btnok_end(void) {
localcmd(sprintf("hostname %s\n", create_tbHostname.m_text));
localcmd(sprintf("sv_playerslots %s\n", create_tbMaxplayers.m_text));
localcmd(sprintf("password %s\n", create_tbPassword.m_text));
localcmd(sprintf("map %s\n", startmap));
g_menupage = PAGE_LANGAMES;
}

View file

@ -39,6 +39,7 @@ float bot_skill[] = {
Bot_AutoAdd
=================
*/
.float delay;
void Bot_AutoAdd( void ) {
if ( self.delay == TRUE ) {
CBot bot;

View file

@ -95,6 +95,25 @@ void ClientDisconnect( void ) {
Effect_RemoveSpray( self );
}
void DecodeChangeParms(void)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
self.angles[0] = parm4;
self.angles[1] = parm5;
self.angles[2] = parm6;
}
void SetChangeParms(void)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = self.angles[0];
parm5 = self.angles[1];
parm6 = self.angles[2];
}
/*
=================
PutClientInServer
@ -103,6 +122,46 @@ Puts a client into the world.
=================
*/
void PutClientInServer( void ) {
if ( cvar( "sv_playerslots" ) == 1 ) {
entity spot;
self.SendEntity = Player_SendEntity;
DecodeChangeParms();
if (startspot) {
self.origin = Landmark_GetSpot();
self.fixangle = TRUE;
} else {
spot = find( world, classname, "info_player_start" );
self.origin = spot.origin;
self.angles = spot.angles;
self.fixangle = TRUE;
}
self.classname = "player";
self.health = self.max_health = 100;
forceinfokey( self, "*dead", "0" );
self.takedamage = DAMAGE_YES;
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_WALK;
self.flags = FL_CLIENT;
self.vPain = Player_Pain;
self.vDeath = Player_Death;
self.iBleeds = TRUE;
self.fSlotGrenade = 0;
self.viewzoom = 1.0;
setmodel( self, "models/player/vip/vip.mdl" );
setsize( self, VEC_HULL_MIN, VEC_HULL_MAX );
self.view_ofs = VEC_PLAYER_VIEWPOS;
self.velocity = '0 0 0';
self.frame = 1; // Idle frame
self.fBombProgress = 0;
self.team = TEAM_CT;
forceinfokey( self, "*spec", "0" );
return;
}
entity eTarget = world;
Spawn_MakeSpectator();

View file

@ -24,6 +24,8 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
#define CLASSEXPORT(classname,classa) void classname ( void ) { spawnfunc_##classa(); }
#define VEC_PLAYER_VIEWPOS '0 0 20'
#define VEC_PLAYER_CVIEWPOS '0 0 12'
@ -148,6 +150,7 @@ void Animation_PlayerTop( float fFrame );
void Animation_PlayerTopTemp( float fFrame, float fTime );
void Footsteps_Update( void );
string startspot;
string __fullspawndata;
hashtable hashMaterials;

View file

@ -288,10 +288,10 @@ void hostage_entity( void ) {
self.eUser = world;
self.eTargetPoint = world;
self.iUsable = TRUE;
self.gflags = GF_USABLE;
self.PlayerUse = hostage_use;
self.iBleeds = TRUE;
self.takedamage = DAMAGE_YES;
self.vUse = hostage_use;
self.vPain = hostage_pain;
self.vDeath = hostage_die;
self.style = HOSTAGE_IDLE;

View file

@ -273,43 +273,3 @@ void Entities_RotateToDestination( vector vDestinationAngle, float fTravelSpeed,
self.vThinkMove = func;
self.think = Entities_RotateToDestination_End;
}
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 );
self.vUse = func_wall_use;
Entities_RenderSetup();
}
void func_illusionary( void ){
func_wall();
self.solid = SOLID_NOT;
}
void func_water( void ) {
func_wall();
self.skin = CONTENT_WATER;
/*self.forceshader = shaderforname( "{\n"
"surfaceparm nodlight\n"
"surfaceparm nomarks\n"
"{\n"
"map $refraction\n"
"}\n"
"{\n"
"map $null\n"
"}\n"
"{\n"
"map $ripplemap\n"
"}\n"
"{\n"
"map $null\n"
"}\n"
"program altwater#RIPPLEMAP#FRESNEL=4\n"
"}\n" );*/
}

View file

@ -120,7 +120,7 @@ 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_NORENDERMODE 4
#define SF_NORENDERCOLOR 8
void env_render( void ) {
@ -246,7 +246,7 @@ void env_spark( void ) {
if ( self.MaxDelay <= 0 ) {
self.MaxDelay = 1.0f;
}
if ( self.spawnflags & SPARK_TOGGLE ) {
if ( self.spawnflags & SPARK_ON ) {
self.think = env_spark_think;

View file

@ -24,6 +24,8 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
.int iStep;
/*
=================
Footsteps_Update
@ -32,67 +34,81 @@ Run every frame for each player, plays material based footsteps
=================
*/
void Footsteps_Update( void ) {
float fForce;
float fDelay;
vector vStep;
string sStepSound = "";
float fSpeed;
float fVol;
string sMaterial = "";
string sTexture = "";
if ( ( self.movetype == MOVETYPE_WALK ) && ( self.flags & FL_ONGROUND ) ) {
if ( ( self.velocity_x == 0 && self.velocity_y == 0 ) || self.fStepTime > time ) {
return;
}
if ( vlen( self.velocity ) < 150 ) {
return;
}
vStep_x = fabs( self.velocity_x );
vStep_y = fabs( self.velocity_y );
fForce = ( vStep_x + vStep_y );
fDelay = clamp( 0.1, 1 / ( fForce / 90 ), 1 );
fSpeed = vlen( self.velocity );
traceline( self.origin + self.view_ofs, self.origin + '0 0 -48', FALSE, self );
string sTexture = getsurfacetexture( trace_ent, getsurfacenearpoint( trace_ent, trace_endpos ) );
sTexture = getsurfacetexture( trace_ent, getsurfacenearpoint( trace_ent, trace_endpos ) );
if ( fSpeed < 140 ) {
self.fStepTime = time + 0.35;
fVol = 0.15f;
} else if ( fSpeed < 270 ) {
self.fStepTime = time + 0.35;
fVol = 0.35f;
} else {
self.fStepTime = time + 0.35;
fVol = 0.75;
}
switch( (float)hash_get( hashMaterials, sTexture ) ) {
case 'M':
sStepSound = sprintf( "player/pl_metal%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "metal";
break;
case 'V':
sStepSound = sprintf( "player/pl_duct%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "duct";
break;
case 'D':
sStepSound = sprintf( "player/pl_dirt%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "dirt";
break;
case 'S':
sStepSound = sprintf( "player/pl_slosh%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "slosh";
break;
case 'T':
sStepSound = sprintf( "player/pl_tile%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "tile";
break;
case 'G':
sStepSound = sprintf( "player/pl_grate%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "grate";
break;
case 'W':
sStepSound = sprintf( "player/pl_step%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "step";
break;
case 'P':
sStepSound = sprintf( "player/pl_step%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "step";
break;
case 'Y':
sStepSound = sprintf( "player/pl_step%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "step";
break;
case 'N':
sStepSound = sprintf( "player/pl_snow%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "snow";
break;
default:
sStepSound = sprintf( "player/pl_step%d.wav", floor( ( random() * 4 ) + 1 ) );
sMaterial = "step";
break;
}
sound( self, CHAN_BODY, sStepSound, 0.5, ATTN_IDLE );
self.fStepTime = time + fDelay;
if ( self.iStep ) {
if ( random() < 0.5f ) {
sound( self, CHAN_BODY, sprintf( "player/pl_%s1.wav", sMaterial), fVol, ATTN_STATIC );
} else {
sound( self, CHAN_BODY, sprintf( "player/pl_%s2.wav", sMaterial), fVol, ATTN_STATIC );
}
} else {
if ( random() < 0.5f ) {
sound( self, CHAN_BODY, sprintf( "player/pl_%s3.wav", sMaterial), fVol, ATTN_STATIC );
} else {
sound( self, CHAN_BODY, sprintf( "player/pl_%s4.wav", sMaterial), fVol, ATTN_STATIC );
}
}
self.iStep = 1 - self.iStep;
}
}

View file

@ -25,7 +25,7 @@
*/
#define SF_BTT_NOMOVE 1
#define SF_BTT_TOGGLE 32
#define SF_BTT_TOGGLE 32
#define SF_BTT_TOUCH_ONLY 256
void() FuncButton_MoveAway;

View file

@ -45,13 +45,12 @@ void func_escapezone_touch( void ) {
forceinfokey( self, "*dead", "0" );
self.health = 0;
Rules_CountPlayers();
self = eOld;
if ( iAlivePlayers_T == 0 ) {
Rules_RoundOver( TEAM_T, 2500, FALSE );
}
}
}
}
/*
@ -65,13 +64,13 @@ 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;

View file

@ -28,8 +28,6 @@ void main( void ) {}
void SetNewParms( void ) {}
void SetChangeParms( void ) {}
void SV_SendChat( entity eSender, string sMessage, entity eEnt, float fType ) {
WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET );
WriteByte( MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM );
@ -658,4 +656,5 @@ void worldspawn( void ) {
pointerstat( STAT_WON_CT, EV_INTEGER, &iWon_CT );
iBombRadius = 1024;
localcmd(sprintf("serverinfo slots %d\n", cvar("sv_playerslots")));
}

View file

@ -155,6 +155,14 @@ void Player_Death( int iHitBody ) {
Player_UseDown
====================
*/
void UseWorkaround( entity eTarget )
{
eActivator = self;
entity eOldSelf = self;
self = eTarget;
self.PlayerUse();
self = eOldSelf;
}
void Player_UseDown( void ) {
if ( self.health <= 0 ) {
return;
@ -163,23 +171,18 @@ void Player_UseDown( void ) {
}
vector vSource;
entity eOriginalSelf;
makevectors(self.v_angle);
vSource = self.origin + self.view_ofs;
traceline ( vSource, vSource + ( v_forward * 64 ), FALSE, self);
if ( trace_ent.iUsable ) {
if (trace_ent.gflags & GF_USABLE) {
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 );
}
eActivator = self;
eOriginalSelf = self;
self = trace_ent;
self.vUse();
self = eOriginalSelf;
UseWorkaround(trace_ent);
} else {
sound( self, CHAN_ITEM, "common/wpn_denyselect.wav", 0.25, ATTN_IDLE );
self.flags = ( self.flags - FL_USERELEASED );

295
Source/Server/Rules.c~ Normal file
View file

@ -0,0 +1,295 @@
/*
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.
*/
enum {
BUY_BOTH,
BUY_CT,
BUY_T,
BUY_NEITHER
};
/*
=================
Rules_BuyingPossible
Checks if it is possible for players to buy anything
=================
*/
float Rules_BuyingPossible( void ) {
if ( self.health <= 0 ) {
return FALSE;
}
if ( fGameState == GAME_ACTIVE ) {
if ( ( ( autocvar_mp_roundtime * 60 ) - fGameTime ) > autocvar_mp_buytime ) {
centerprint( self, sprintf( "%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime ) );
self.fAttackFinished = time + 1.0;
return FALSE;
}
}
if ( self.team == TEAM_VIP ) {
centerprint( self, "You are the VIP...\nYou can't buy anything!\n" );
self.fAttackFinished = time + 1.0;
return FALSE;
}
if ( iBuyRestriction == BUY_NEITHER ) {
centerprint( self, "Sorry, you aren't meant\nto be buying anything.\n" );
self.fAttackFinished = time + 1.0;
return FALSE;
}
if ( iBuyRestriction != BUY_BOTH ) {
if ( iBuyRestriction == BUY_CT && self.team == TEAM_T ) {
centerprint( self, "Terrorists aren't allowed to\nbuy anything on this map!\n" );
self.fAttackFinished = time + 1.0;
return FALSE;
} else if ( iBuyRestriction == BUY_T && self.team == TEAM_CT ) {
centerprint( self, "CTs aren't allowed to buy\nanything on this map!\n" );
self.fAttackFinished = time + 1.0;
return FALSE;
}
}
if ( self.fInBuyZone == FALSE ) {
return FALSE;
}
return TRUE;
}
void Rules_MakeBomber( void ) {
Weapon_AddItem( WEAPON_C4BOMB );
centerprint( self, "You have the bomb!\nFind the target zone or DROP\nthe bomb for another Terrorist." );
}
void Rules_MakeVIP( void ) {
self.team = TEAM_VIP;
Spawn_RespawnClient( self.team );
centerprint( self, "You are the VIP\nMake your way to the safety zones!" );
forceinfokey( self, "*dead", "2" );
}
/*
=================
Rules_Restart
Loop through all ents and handle them
=================
*/
void Rules_Restart( int iWipe ) {
iHostagesRescued = 0;
entity eOld = self;
// Spawn/Respawn everyone at their team position and give them $$$
for ( entity eFind = world; ( eFind = find( eFind, classname, "player" ) ); ) {
self = eFind;
if ( self.health > 0 && iWipe == FALSE ) {
Spawn_RespawnClient( self.team );
} else {
Spawn_MakeSpectator();
Spawn_CreateClient( self.fCharModel );
}
if ( iWipe == FALSE ) {
Money_GiveTeamReward();
} else {
self.fMoney = autocvar_mp_startmoney;
}
}
// Clear the corpses/items
for ( entity eFind = world; ( eFind = find( eFind, classname, "remove_me" ) ); ) {
remove( eFind );
}
// Find the bombs. Destory them!
for ( entity eFind = world; ( eFind = find( eFind, classname, "c4bomb" ) ); ) {
remove( eFind );
}
// Select a random Terrorist for the bomb, if needed
if ( iBombZones > 0 ) {
int iRandomT = floor( random( 1, (float)iAlivePlayers_T + 1 ) );
int iPickT = 0;
for ( entity eFind = world; ( eFind = find( eFind, classname, "player" ) ); ) {
if ( eFind.team == TEAM_T ) {
iPickT++;
if ( iPickT == iRandomT ) {
self = eFind;
Rules_MakeBomber();
}
}
}
}
// If there is a VIP, select a random CT to be it
if ( iVIPZones > 0 ) {
int iRandomCT = floor( random( 1, (float)iAlivePlayers_CT + 1 ) );
int iPickCT = 0;
for ( entity eFind = world; ( eFind = find( eFind, classname, "player" ) ); ) {
if ( eFind.team == TEAM_CT ) {
iPickCT++;
if ( iPickCT == iRandomCT ) {
self = eFind;
Rules_MakeVIP();
}
}
}
}
// Respawn all the entities
for ( entity eFind = world; ( eFind = findfloat( eFind, fRespawns, TRUE ) ); ) {
self = eFind;
Entities_Respawn();
}
self = eOld;
Timer_Begin( autocvar_mp_freezetime, GAME_FREEZE );
Money_ResetTeamReward();
}
/*
=================
Rules_RoundOver
This happens whenever an objective is complete or time is up
=================
*/
void Rules_RoundOver( int iTeamWon, int iMoneyReward, float fSilent ) {
if ( fGameState != GAME_ACTIVE ) {
return;
}
if ( iTeamWon == TEAM_T ) {
if ( fSilent == FALSE ) {
Radio_BroadcastMessage( RADIO_TERWIN );
}
iWon_T++;
// FIXME: Calculate the proper loss values
Money_QueTeamReward( TEAM_CT, 1400 );
} else if ( iTeamWon == TEAM_CT ) {
if ( fSilent == FALSE ) {
Radio_BroadcastMessage( RADIO_CTWIN );
}
iWon_CT++;
// FIXME: Calculate the proper loss values
Money_QueTeamReward( TEAM_T, 1400 );
} else {
if ( fSilent == FALSE ) {
Radio_BroadcastMessage( RADIO_ROUNDDRAW );
}
}
Money_QueTeamReward( iTeamWon, iMoneyReward );
Timer_Begin( 5, GAME_END); // Round is over, 5 seconds til a new round starts
iBombPlanted = 0;
iRounds++;
}
/*
=================
Rules_TimeOver
Whenever mp_roundtime was being counted down to 0
=================
*/
void Rules_TimeOver( void ) {
if ( iVIPZones > 0 ) {
Rules_RoundOver( TEAM_T, 3250, FALSE );
} else if ( iBombZones > 0 ) {
Rules_RoundOver( TEAM_CT, 3250, FALSE );
} else if ( iHostagesMax > 0 ) {
// TODO: Broadcast_Print: Hostages have not been rescued!
Rules_RoundOver( TEAM_T, 3250, FALSE );
} else {
Rules_RoundOver( 0, 0, FALSE );
}
}
/*
=================
Rules_SwitchTeams
Happens rarely
=================
*/
void Rules_SwitchTeams( void ) {
int iCTW, iTW;
for ( entity eFind = world; ( eFind = find( eFind, classname, "player" ) ); ) {
if ( eFind.team == TEAM_CT ) {
eFind.team = TEAM_T;
eFind.fCharModel -= 4;
} else if ( eFind.team == TEAM_T ) {
eFind.team = TEAM_CT;
eFind.fCharModel += 4;
}
forceinfokey( eFind, "*team", ftos( eFind.team ) );
}
iCTW = iWon_CT;
iTW = iWon_T;
iWon_T = iCTW;
iWon_CT = iTW;
iCTW = iAlivePlayers_CT;
iTW = iAlivePlayers_T;
iAlivePlayers_CT = iTW;
iAlivePlayers_T = iCTW;
}
/*
=================
SPAWN: info_map_parameters
Let's map authors decide who can buy stuff and who CAN'T.
Also allows people to set the bomb placing radius incase you want to use info_bomb_target.
=================
*/
.float buying;
.float bombradius;
void info_map_parameters( void ) {
if ( self.bombradius ) {
iBombRadius = self.bombradius;
}
if ( self.buying ) {
iBuyRestriction = self.buying;
}
}

View file

@ -362,17 +362,6 @@ void info_player_terrorist(void)
info_player_deathmatch();
}
/*
=================
info_target
Cameras use this thing
=================
*/
void info_target( void ) {
setorigin( self, self.origin );
}
/*
=================
info_vip_start

View file

@ -57,6 +57,11 @@ Called once every frame to check the status of things
void Timer_Update(void) {
static float fVoxTimer;
if ( cvar( "sv_playerslots" ) == 1 ) {
fGameTime = -1;
return;
}
// This map has been played enough we think
if (fGameState != GAME_OVER) {
if (cvar("mp_timelimit") > 0) {

View file

@ -1,5 +1,4 @@
#pragma target fte
#pragma progs_dat "../../freecs/progs.dat"
#includelist
@ -8,6 +7,7 @@
../Math.h
Defs.h
DefsFields.h
../gs-entbase/server/defs.h
Money.c
../Shared/Animations.c
@ -53,30 +53,69 @@ Rules.c
Timer.c
EntHostage.c
../gs-entbase/server/baseentity.cpp
../gs-entbase/server/basetrigger.cpp
../gs-entbase/server/ambient_generic.cpp
../gs-entbase/server/env_beam.cpp
../gs-entbase/server/env_fade.cpp
../gs-entbase/server/env_sprite.cpp
../gs-entbase/server/env_spark.cpp
../gs-entbase/server/env_explosion.cpp
../gs-entbase/server/env_render.cpp
../gs-entbase/server/env_glow.cpp
../gs-entbase/server/env_shake.cpp
../gs-entbase/server/func_recharge.cpp
../gs-entbase/server/func_healthcharger.cpp
../gs-entbase/server/func_breakable.cpp
../gs-entbase/server/func_button.cpp
../gs-entbase/server/func_door.cpp
../gs-entbase/server/func_door_rotating.cpp
../gs-entbase/server/func_illusionary.cpp
../gs-entbase/server/func_ladder.cpp
../gs-entbase/server/func_train.cpp
../gs-entbase/server/func_wall.cpp
../gs-entbase/server/func_conveyor.cpp
../gs-entbase/server/func_rotating.cpp
../gs-entbase/server/light.cpp
../gs-entbase/server/stubs.cpp
../gs-entbase/server/trigger_auto.cpp
../gs-entbase/server/trigger_cdaudio.cpp
../gs-entbase/server/trigger_camera.cpp
../gs-entbase/server/trigger_hurt.cpp
../gs-entbase/server/trigger_changelevel.cpp
../gs-entbase/server/trigger_once.cpp
../gs-entbase/server/trigger_multiple.cpp
../gs-entbase/server/trigger_push.cpp
../gs-entbase/server/trigger_teleport.cpp
../gs-entbase/server/trigger_transition.cpp
../gs-entbase/server/trigger_relay.cpp
../gs-entbase/server/env_shooter.cpp
../gs-entbase/server/env_beverage.cpp
../gs-entbase/server/env_global.cpp
../gs-entbase/server/item_food.cpp
../gs-entbase/server/item_suit.cpp
../gs-entbase/server/multi_manager.cpp
../gs-entbase/server/monster_furniture.cpp
../gs-entbase/server/monster_generic.cpp
../gs-entbase/server/multisource.cpp
../gs-entbase/server/scripted_sequence.cpp
//../gs-entbase/server/info_player_start.cpp
//../gs-entbase/server/info_player_deathmatch.cpp
Entities.c
Triggers.c
EnvObjects.c
FuncBreakable.c
FuncPushable.c
FuncLadder.c
FuncHostageRescue.c
FuncVIPSafetyZone.c
FuncEscapeZone.c
FuncBombTarget.c
FuncBuyZone.c
FuncButton.c
FuncDoor.c
FuncDoorRotating.c
FuncVehicle.c
ArmouryEntity.c
AmbientSound.c
InfoDecal.c
FuncVIPSafetyZone.c
InfoDecal.c
ArmouryEntity.c
Bot/Bot.h
Bot/Way.c
Light.c
Main.c
Player.c
Spawn.c

View file

@ -178,8 +178,8 @@ void WeaponC4BOMB_Drop( vector vBombPos, vector vNormal ) {
eBomb.customphysics = WeaponC4BOMB_Think;
eBomb.fAttackFinished = time + autocvar_mp_c4timer;
eBomb.vUse = WeaponC4BOMB_Use;
eBomb.iUsable = TRUE;
eBomb.gflags = GF_USABLE;
eBomb.PlayerUse = WeaponC4BOMB_Use;
eBomb.owner = self;
// Align the bomb to the wall

View file

@ -0,0 +1,95 @@
/***
*
* Copyright (c) 2000-2019, Vera Visions. All rights reserved.
*
****/
#ifndef FADEOVERLAY
#define FADEOVERLAY
#endif
float g_flFadeDuration;
float g_flFadeHold;
float g_flFadeMaxAlpha;
float g_flFadeStyle;
float g_flFadeAlpha;
float g_flFadeTime;
vector g_vecFadeColor;
int g_iFadeActive;
/*enum
{
DRAWFLAG_NORMAL,
DRAWFLAG_ADDITIVE,
DRAWFLAG_MODULATE, // FTE doesn't support this
DRAWFLAG_2XMODULATE // FTE doesn't support this
};*/
enumflags
{
EVF_FADEDROM,
EVF_MODULATE,
EVF_ONLYUSER
};
void Fade_Init ( void )
{
shaderforname( "fade_modulate","{\n{\nmap $whiteimage\nrgbGen vertex\nblendFunc GL_DST_COLOR GL_ONE_MINUS_SRC_ALPHA\nalphaGen vertex\n}\n}\n" );
}
void Fade_Update ( float x, float y, float w, float h )
{
if ( g_iFadeActive == FALSE ) {
return;
}
if ( g_flFadeStyle & EVF_FADEDROM ) {
if ( g_flFadeTime > g_flFadeHold ) {
g_flFadeAlpha -= ( frametime * ( 1.0f / g_flFadeDuration ) ) * g_flFadeMaxAlpha;
}
} else {
if ( g_flFadeTime < g_flFadeDuration ) {
g_flFadeAlpha += ( frametime * ( 1.0f / g_flFadeDuration ) ) * g_flFadeMaxAlpha;
} else {
g_flFadeAlpha -= ( frametime * ( 1.0f / g_flFadeHold ) ) * g_flFadeMaxAlpha;
}
}
if ( g_flFadeAlpha > 1.0f ) {
g_flFadeAlpha = 1.0f;
} else if ( g_flFadeAlpha < 0.0f ) {
g_flFadeAlpha = 0.0f;
}
if ( g_flFadeAlpha <= 0 ) {
g_iFadeActive = FALSE;
return;
}
if ( g_flFadeStyle & EVF_MODULATE ) {
drawpic( [x, y], "fade_modulate", [w, h], g_vecFadeColor, g_flFadeAlpha, 0 );
} else {
drawfill( [x, y], [w, h], g_vecFadeColor, g_flFadeAlpha, 0 );
}
g_flFadeTime += frametime;
}
void Fade_Parse ( void )
{
g_vecFadeColor[0] = readbyte() / 255;
g_vecFadeColor[1] = readbyte() / 255;
g_vecFadeColor[2] = readbyte() / 255;
g_flFadeMaxAlpha = readbyte() / 255;
g_flFadeDuration = readfloat();
g_flFadeHold = readfloat();
g_flFadeStyle = readbyte();
g_flFadeTime = 0.0f;
if ( g_flFadeStyle & EVF_FADEDROM ) {
g_flFadeAlpha = 1.0f;
} else {
g_flFadeAlpha = 0.0f;
}
g_iFadeActive = TRUE;
}

View file

@ -0,0 +1,29 @@
HALF-LIFE ENTITY BASE - QUAKEC VERSION
======================================
This server-side logic is part of the FreeCS project.
It's a reverse-engineering effort to get Half-Life entities closely
compatible with FTE QuakeWorld.
They are made possible through the documentation efforts of https://twhl.info
It's created from scratch and is not C++ - it's QuakeC and meant to be used
within FTE QuakeWorld. The file extensions are only changed in order to help
with the syntax highlighting choice of your favorite editor.
This codebase is to be compiled with FTEQCC, no other compiler is supported.
The code has a LICENSE attached to it, I'd encourage you to read it.
If you don't want to comply with the LICENSE, you either don't use the software
or we could still negotiate a separate license agreement (for $$$).
A few warnings to the uneducated:
If you're planning on merging or using any of this code in combination with the
original Half-Life SDK, you're violating the Half-Life SDK License Agreement.
I hope this all does not discourage you from using it for your own project.
Thanks to Spike for FTEQCC's advanced features and his engine, FTEQW, that makes
FreeCS and other projects even possible.
Marco 'eukara' Hladik

View file

@ -0,0 +1,132 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags
{
AS_ARADIUS,
AS_SRADIUS,
AS_MRADIUS,
AS_LRADIUS,
AS_SILENT,
AS_NOTTOGGLED
};
class CAmbientGeneric : CBaseTrigger {
string m_strActivePath;
string m_strSoundPath;
float m_flVolume;
float m_flRadius;
int m_iToggleSwitch;
float m_flPitch;
int m_iLoop;
/* int m_iPreset;
float m_flVolume_Start;
float m_flFadeIn;
float m_flFadeOut;*/ // TODO: Do this in CSQC
void() CAmbientGeneric;
};
static float CAmbientGeneric::Network(entity ePEnt, float fChanged)
{
WriteByte( MSG_ENTITY, ENT_AMBIENTSOUND );
WriteCoord( MSG_ENTITY, origin[0] );
WriteCoord( MSG_ENTITY, origin[1] );
WriteCoord( MSG_ENTITY, origin[2] );
WriteString( MSG_ENTITY, m_strActivePath );
WriteFloat( MSG_ENTITY, m_flVolume );
WriteByte( MSG_ENTITY, m_flRadius );
WriteByte( MSG_ENTITY, m_iLoop );
WriteByte( MSG_ENTITY, 0 );
return TRUE;
}
void CAmbientGeneric::UseNormal( void )
{
sound(this, CHAN_VOICE, m_strActivePath, m_flVolume, m_flRadius, m_flPitch);
}
void CAmbientGeneric::UseLoop( void )
{
if ( m_iToggleSwitch == TRUE ) {
m_strActivePath = "common/null.wav";
SendFlags = 128;
m_iToggleSwitch = FALSE;
} else {
m_strActivePath = m_strSoundPath;
SendFlags = 128;
m_iToggleSwitch = TRUE;
}
}
void CAmbientGeneric::CAmbientGeneric ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "message":
m_strSoundPath = argv( i + 1 );
m_strActivePath = m_strSoundPath;
message = __NULL__;
break;
case "health":
m_flVolume = stof( argv( i + 1 ) ) * 0.1f;
health = __NULL__;
break;
case "volume":
m_flVolume = stof( argv( i + 1 ) );
//volume = __NULL__;
break;
case "pitch":
m_flPitch = stof( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !m_strSoundPath ) {
objerror( "CAmbientGeneric: No sound file specified. Aborting." );
}
precache_sound( m_strSoundPath );
if ( !m_flVolume ) {
m_flVolume = 1.0f;
}
// There can be only one
if ( spawnflags & AS_ARADIUS ) {
m_flRadius = ATTN_NONE;
} else if ( spawnflags & AS_SRADIUS ) {
m_flRadius = ATTN_IDLE;
} else if ( spawnflags & AS_MRADIUS ) {
m_flRadius = ATTN_STATIC;
} else if ( spawnflags & AS_LRADIUS ) {
m_flRadius = ATTN_NORM;
} else {
m_flRadius = ATTN_STATIC;
}
if ( spawnflags & AS_NOTTOGGLED ) {
m_iLoop = FALSE;
} else {
m_iLoop = TRUE;
}
if( spawnflags & AS_SILENT ) {
Trigger = UseNormal;
} else {
pvsflags = PVSF_NOREMOVE | PVSF_IGNOREPVS;
Trigger = UseLoop;
SendEntity = Network;
m_iToggleSwitch = FALSE;
}
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT( ambient_generic, CAmbientGeneric )

View file

@ -0,0 +1,98 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enum
{
RM_NORMAL,
RM_COLOR,
RM_TEXTURE,
RM_GLOW,
RM_SOLID,
RM_ADDITIVE
};
class CBaseEntity
{
string m_oldModel;
float m_oldSolid;
float m_oldHealth;
vector m_oldOrigin;
vector m_oldAngle;
float m_rendermode;
float m_renderamt;
vector m_rendercolor;
void() CBaseEntity;
virtual void() Respawn;
virtual void() Hide;
virtual void() RendermodeUpdate;
};
void CBaseEntity :: CBaseEntity ( void )
{
gflags |= GF_CANRESPAWN;
m_oldModel = model;
m_oldSolid = solid;
m_oldHealth = health;
m_oldOrigin = origin;
m_oldAngle = angles;
int nfields = tokenize( __fullspawndata );
for ( int i = 1; i < ( nfields - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "renderamt":
m_renderamt = stof( argv( i + 1 ) );
break;
case "rendercolor":
m_rendercolor = stov( argv( i + 1 ) );
break;
case "rendermode":
m_rendermode = stof( argv( i + 1 ) );
break;
default:
break;
}
}
RendermodeUpdate();
}
void CBaseEntity::RendermodeUpdate(void)
{
if ( m_rendermode != RM_NORMAL ) {
alpha = ( m_renderamt / 255 );
colormod = m_rendercolor;
if( alpha == 0 ) {
alpha = 0.0001;
}
if ( m_rendermode == RM_ADDITIVE ) {
effects = EF_ADDITIVE; // QWSSQC: EF_FLAG2
} else if ( m_rendermode == RM_GLOW ) {
effects = EF_ADDITIVE | EF_FULLBRIGHT;
}
}
}
void CBaseEntity :: Respawn ( void )
{
model = m_oldModel;
solid = m_oldSolid;
health = m_oldHealth;
origin = m_oldOrigin;
angles = m_oldAngle;
setorigin( this, origin );
setmodel( this, model );
}
void CBaseEntity :: Hide ( void )
{
setmodel( this, "" );
solid = SOLID_NOT;
movetype = MOVETYPE_NONE;
}

View file

@ -0,0 +1,122 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enum {
USE_TOGGLE,
USE_CONTINOUS
};
class CBaseTrigger : CBaseEntity
{
int m_strGlobalState;
string m_strTarget;
string m_strTargetName;
string m_strKillTarget;
string m_strMessage;
int m_iUseType;
void() CBaseTrigger;
virtual void() Trigger;
virtual void() UseTargets;
virtual int() GetValue;
virtual void( float del ) UseTargets_Delay;
virtual void() InitBrushTrigger;
virtual void() InitPointTrigger;
};
void CBaseTrigger :: UseTargets ( void )
{
for ( entity eFind = world; ( eFind = find( eFind, CBaseTrigger::m_strTargetName, m_strTarget ) ); ) {
CBaseTrigger trigger = (CBaseTrigger) eFind;
#ifdef GS_DEVELOPER
print( sprintf( "%s: Triggering %s `%s`\n",
this.classname, eFind.classname, trigger.m_strTargetName ) );
#endif
trigger.Trigger();
}
if ( m_strKillTarget ) {
entity eKill = find( world, CBaseTrigger::m_strTargetName, m_strKillTarget );
if ( eKill ) {
remove( eKill );
}
}
}
int CBaseTrigger :: GetValue ( void )
{
return TRUE;
}
void CBaseTrigger :: UseTargets_Delay ( float fDelay )
{
static void Entities_UseTargets_Delay_Think( void ) {
CBaseTrigger::UseTargets();
remove( self );
}
#ifdef GS_DEVELOPER
print( sprintf( "CBaseTrigger: Delaying trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger eTimer = spawn( CBaseTrigger );
eTimer.owner = self;
eTimer.think = Entities_UseTargets_Delay_Think;
eTimer.m_strTarget = m_strTarget;
eTimer.nextthink = time + fDelay;
}
void CBaseTrigger :: Trigger ( void )
{
}
void CBaseTrigger :: InitPointTrigger ( void )
{
setsize( this, VEC_HULL_MIN, VEC_HULL_MAX );
solid = SOLID_TRIGGER;
}
void CBaseTrigger :: InitBrushTrigger ( void )
{
precache_model( model );
setmodel( this, model );
movetype = MOVETYPE_NONE;
#ifdef GS_DEVELOPER
alpha = 0.5f;
effects = EF_ADDITIVE;
#else
modelindex = 0;
model = "";
#endif
solid = SOLID_TRIGGER;
}
void CBaseTrigger :: CBaseTrigger ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "target":
m_strTarget = argv( i + 1 );
target = __NULL__;
break;
case "targetname":
m_strTargetName = argv( i + 1 );
targetname = __NULL__;
break;
case "killtarget":
m_strKillTarget = argv( i + 1 );
break;
case "message":
m_strMessage = argv( i + 1);
break;
default:
break;
}
}
CBaseEntity::CBaseEntity();
}

View file

@ -0,0 +1,41 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// TODO: Complete this once damage is done
/*
* cycler - Point Entity
The cycler entity is a model viewer of sorts. It places a model within the map which, when attacked, will cycle its animation.
Attributes
Name (targetname) - Name is a general attribute used to identify entities.
Pitch Yaw Roll (Y Z X) (angles) - Sets the pitch, yaw and roll angles of the model.
Animation Sequence (editor) (sequence) - Sets the animation the model should start in. Setting this to anything other than 0 seems to place the cycler into its triggered mode (see notes).
Model (model) - This defines which model file will be displayed by the entity. This accepts an input of the form "path/filename.mdl" (starting from the root folder). (Example: "models/scientist.mdl").
Render FX (renderfx) - Gives the model certain visual effects depending on Render Mode.
Render Mode (rendermode) - Allows special rendering modes to be applied to the given entity.
FX Amount (1 - 255) (renderamt) - In all but "Normal" Render Mode, alters how transparent the model is. Scales from 0 (invisible) to 255 (solid, normal).
FX Color (R G B) (rendercolour) - Seemingly unused.
Notes
Triggering or pressing use on the cycler will freeze the model in its current animation. In this state, shooting the cycler will have it step through frames of the animation it was in. Triggering it or using it again will return it to its normal function.
Given the way this entity behaves, there is little practical use for this entity beyond viewing animations (for which there are programs that are far more convenient).
*/
class CCycler : CBaseEntity
{
void() CCycler;
};
void CCycler :: CCycler ( void )
{
precache_model( model );
CBaseEntity::CBaseEntity();
setmodel( this, model );
solid = SOLID_BBOX;
}

View file

@ -0,0 +1,30 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define GS_DEVELOPER
.float gflags;
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
};

View file

@ -0,0 +1,18 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CEnvBeam {
void() CEnvBeam;
};
void CEnvBeam :: CEnvBeam ( void )
{
}
CLASSEXPORT( env_beam, CEnvBeam )

View file

@ -0,0 +1,72 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// Dependency from item_food.cpp
void item_sodacan( void );
// TODO: Implement support for skins
enum
{
SKIN_COCACOLA,
SKIN_SPRITE,
SKIN_DIETCOKE,
SKIN_ORANGE,
SKIN_SURGE,
SKIN_MOXIE,
SKIN_RANDOM
};
class CEnvBeverage : CBaseTrigger
{
int m_iUses;
int m_iReady;
int m_iSkin;
void() CEnvBeverage;
virtual void() Trigger;
};
void CEnvBeverage :: Trigger ( void )
{
if ( m_iReady == FALSE || m_iUses <= 0 ) {
return;
}
entity eCan = spawn();
setorigin( eCan, origin );
eCan.angles = angles;
eCan.owner = this;
eCan.think = item_sodacan;
eCan.nextthink = time;
m_iUses--;
m_iReady = FALSE;
}
void CEnvBeverage :: CEnvBeverage ( void )
{
precache_model( "models/can.mdl" );
precache_sound( "weapons/g_bounce3.wav" );
CBaseTrigger::CBaseTrigger();
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "health":
m_iUses = stoi( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !m_iUses ) {
m_iUses = 10;
}
m_iReady = TRUE;
}
CLASSEXPORT( env_beverage, CEnvBeverage )

View file

@ -0,0 +1,54 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags {
ENVEXPLO_NODAMAGE,
ENVEXPLO_REPEATABLE,
ENVEXPLO_NOBALL,
ENVEXPLO_NOSMOKE,
ENVEXPLO_NODECAL,
ENVEXPLO_NOSPARKS
};
class CEnvExplosion:CBaseTrigger
{
int m_iMagnitude;
float m_flMaxDelay;
void() CEnvExplosion;
virtual void() Trigger;
};
void CEnvExplosion::CEnvExplosion(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "iMagnitude":
m_iMagnitude = stoi(argv(i + 1));
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
}
void CEnvExplosion::Trigger(void)
{
Effect_CreateExplosion(origin);
if (!(spawnflags & ENVEXPLO_NODAMAGE)) {
Damage_Radius(origin, this, 500, m_iMagnitude, TRUE);
}
// TODO: Respawn after round instead?
if (!(spawnflags & ENVEXPLO_REPEATABLE)) {
remove(this);
}
}
CLASSEXPORT(env_explosion, CEnvExplosion)

View file

@ -0,0 +1,62 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags
{
EVF_FADEDROM,
EVF_MODULATE,
EVF_ONLYUSER
};
class CEnvFade : CBaseTrigger
{
float m_flFadeDuration;
float m_flFadeHold;
void() CEnvFade;
virtual void() Trigger;
};
void CEnvFade :: Trigger (void)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_FADE);
WriteByte(MSG_MULTICAST, m_rendercolor[0]);
WriteByte(MSG_MULTICAST, m_rendercolor[1]);
WriteByte(MSG_MULTICAST, m_rendercolor[2]);
WriteByte(MSG_MULTICAST, m_renderamt);
WriteFloat(MSG_MULTICAST, m_flFadeDuration);
WriteFloat(MSG_MULTICAST, m_flFadeHold);
WriteByte(MSG_MULTICAST, spawnflags);
msg_entity = eActivator;
if (spawnflags & EVF_ONLYUSER) {
multicast('0 0 0', MULTICAST_ONE_R);
} else {
multicast('0 0 0', MULTICAST_ALL);
}
}
void CEnvFade :: CEnvFade (void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "duration":
m_flFadeDuration = stof(argv(i + 1));
break;
case "holdtime":
m_flFadeHold = stof(argv(i + 1));
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT(env_fade, CEnvFade)

View file

@ -0,0 +1,127 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define GLOBAL_SETSPAWN 1
enum
{
GLOBAL_OFF,
GLOBAL_ON,
GLOBAL_DEAD
};
const string CENVGLOBAL_CVAR = "env_global_data";
class CEnvGlobal : CBaseTrigger
{
string m_strGlobalState;
int m_iTriggerMode;
int m_iInitialState;
void() CEnvGlobal;
virtual void() Trigger;
virtual int( string ) GlobalPresent;
virtual void( string, int ) AddNewGlobal;
virtual void( string, int ) SetGlobal;
virtual int( string ) GetGlobal;
};
void CEnvGlobal :: Trigger ( void ) {
int iOldValue = GetGlobal( m_strGlobalState );
int iNewValue = 0;
switch( m_iTriggerMode ) {
case 0:
iNewValue = GLOBAL_OFF;
break;
case 1:
iNewValue = GLOBAL_ON;
break;
case 2:
iNewValue = GLOBAL_DEAD;
break;
default:
if ( iOldValue == GLOBAL_ON ) {
iNewValue = GLOBAL_OFF;
} else if ( iOldValue == GLOBAL_OFF ) {
iNewValue = GLOBAL_ON;
} else {
iNewValue = iOldValue;
}
}
if ( GlobalPresent( m_strGlobalState ) ) {
SetGlobal( m_strGlobalState, iNewValue );
} else {
AddNewGlobal( m_strGlobalState, iNewValue );
}
}
int CEnvGlobal :: GlobalPresent ( string strName ) {
for ( int i = 1; i < ( tokenize( cvar_string( CENVGLOBAL_CVAR ) ) - 1 ); i += 2 ) {
if ( argv( i ) == strName ) {
return 1;
}
}
return 0;
}
void CEnvGlobal :: AddNewGlobal ( string strName, int iValue ) {
cvar_set( CENVGLOBAL_CVAR, sprintf( "%s %s %i", cvar_string( CENVGLOBAL_CVAR ), strName, iValue ) );
}
void CEnvGlobal :: SetGlobal ( string strName, int iValue ) {
string strNewData = "";
for ( int i = 1; i < ( tokenize( cvar_string( CENVGLOBAL_CVAR ) ) - 1 ); i += 2 ) {
if ( argv( i ) != strName ) {
strNewData = sprintf( "%s %s %s", strNewData, argv( i ), argv( i + 1 ) );
}
}
cvar_set( CENVGLOBAL_CVAR, sprintf( "%s %s %i", strNewData, strName, iValue ) );
}
int CEnvGlobal :: GetGlobal ( string strName ) {
for ( int i = 1; i < ( tokenize( cvar_string( CENVGLOBAL_CVAR ) ) - 1 ); i += 2 ) {
if ( argv( i ) == strName ) {
return stoi( argv( i + 1 ) );
}
}
return 0;
}
void CEnvGlobal :: CEnvGlobal ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "globalstate":
m_strGlobalState = argv( i + 1 );
break;
case "triggermode":
m_iTriggerMode = stoi( argv( i + 1 ) );
break;
case "initialstate":
m_iInitialState = stoi( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !m_strGlobalState ) {
objerror( "CEnvGlobal: No globalstate name given! Aborting\n" );
}
if ( spawnflags & GLOBAL_SETSPAWN ) {
if ( !GlobalPresent( m_strGlobalState ) ) {
AddNewGlobal( m_strGlobalState, m_iInitialState );
}
}
}
CLASSEXPORT( env_global, CEnvGlobal )

View file

@ -0,0 +1,28 @@
/***
*
* 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/env_sprite_(Half-Life) */
enumflags {
ENVS_STARTON,
ENVS_PLAYONCE
};
class CEnvGlow : CBaseEntity
{
void() CEnvGlow;
};
void CEnvGlow::CEnvGlow(void)
{
CBaseEntity::CBaseEntity();
precache_model(m_oldModel);
Respawn();
}
CLASSEXPORT(env_glow, CEnvGlow)

View file

@ -0,0 +1,39 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags {
SF_NORENDERFX,
SF_NORENDERAMT,
SF_NORENDERMODE,
SF_NORENDERCOLOR
};
class CEnvRender:CBaseTrigger
{
virtual void() Trigger;
};
void CEnvRender::Trigger(void)
{
for (entity eFind = world;
(eFind = find(eFind, CBaseTrigger::m_strTargetName, m_strTarget));) {
CBaseEntity trigger = (CBaseEntity) eFind;
if (!(spawnflags & SF_NORENDERMODE)) {
trigger.m_rendermode = m_rendermode;
}
if (!(spawnflags & SF_NORENDERCOLOR)) {
trigger.m_rendercolor = m_rendercolor;
}
if (!(spawnflags & SF_NORENDERAMT)) {
trigger.m_renderamt = m_renderamt;
}
trigger.RendermodeUpdate();
}
}
CLASSEXPORT(env_render, CEnvRender)

View file

@ -0,0 +1,59 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define EVS_GLOBAL 1
class CEnvShake : CBaseTrigger
{
float m_flRadius;
float m_flAmplitude;
float m_flDuration;
float m_flFrequency;
void() CEnvShake;
virtual void() Trigger;
};
void CEnvShake :: Trigger (void)
{
for (entity eClients = world; (eClients = find(eClients, ::classname, "Player"));) {
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SHAKE);
WriteFloat(MSG_MULTICAST, m_flRadius);
WriteFloat(MSG_MULTICAST, m_flAmplitude);
WriteFloat(MSG_MULTICAST, m_flDuration);
WriteFloat(MSG_MULTICAST, m_flFrequency);
msg_entity = eClients;
multicast('0 0 0', MULTICAST_ONE_R);
}
}
void CEnvShake :: CEnvShake (void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "radius":
m_flRadius = stof(argv(i + 1));
break;
case "amplitude":
m_flAmplitude = stof(argv(i + 1));
break;
case "duration":
m_flDuration = stof(argv(i + 1));
break;
case "frequency":
m_flFrequency = stof(argv(i + 1));
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT(env_shake, CEnvShake)

View file

@ -0,0 +1,77 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CEnvShooter : CBaseTrigger
{
float m_iGibs;
float m_flDelay;
float m_flVelocity;
float m_flVariance;
float m_flGibLife;
string m_strShootModel;
float m_flShootSounds;
float m_flScale;
float m_flSkin;
};
void CEnvShooter :: Trigger ( void )
{
static void Gib_Remove ( void ) { remove( self ); }
for ( int i = 0; i < m_iGibs; i++ ) {
entity eGib = spawn();
eGib.movetype = MOVETYPE_BOUNCE;
setmodel( eGib, m_strShootModel );
makevectors( angles );
eGib.velocity = v_forward * m_flVelocity;
eGib.think = Gib_Remove;
eGib.nextthink = m_flGibLife;
}
}
void CEnvShooter :: CEnvShooter ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "m_iGibs":
m_iGibs = stoi( argv( i + 1 ) );
break;
case "m_flDelay":
m_flDelay = stof( argv( i + 1 ) );
break;
case "m_flVelocity":
m_flVelocity = stof( argv( i + 1 ) );
break;
case "m_flVariance":
m_flVariance = stof( argv( i + 1 ) );
break;
case "m_flGibLife":
m_flGibLife = stof( argv( i + 1 ) );
break;
case "shootmodel":
m_strShootModel = argv( i + 1 );
break;
case "shootsounds":
m_flShootSounds = stof( argv( i + 1 ) );
break;
case "scale":
m_flScale = stof( argv( i + 1 ) );
break;
case "skin":
m_flSkin = stof( argv( i + 1 ) );
break;
default:
break;
}
}
precache_model( m_strShootModel );
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT( env_shooter, CEnvShooter )

View file

@ -0,0 +1,98 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags {
EVSPARK_UNUSED1,
EVSPARK_UNUSED2,
EVSPARK_UNUSED3,
EVSPARK_UNUSED4,
EVSPARK_UNUSED5,
EVSPARK_TOGGLE,
EVSPARK_STARTON
};
string spark_snd[] = {
"buttons/spark1.wav",
"buttons/spark2.wav",
"buttons/spark3.wav",
"buttons/spark4.wav",
"buttons/spark5.wav",
"buttons/spark6.wav"
};
class CEnvSpark:CBaseTrigger
{
float m_flMaxDelay;
void() CEnvSpark;
virtual void() CreateSpark;
virtual void() TimedSpark;
virtual void() Trigger;
virtual void() Respawn;
};
void CEnvSpark::CEnvSpark(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "MaxDelay":
m_flMaxDelay = stof(argv(i + 1));
break;
default:
break;
}
}
for (int i = 0; i < spark_snd.length; i++) {
precache_sound(spark_snd[i]);
}
CBaseTrigger::CBaseTrigger();
Respawn();
}
void CEnvSpark::CreateSpark(void)
{
int r = floor((random() * 6));
sound(this, CHAN_AUTO, spark_snd[r], 1.0f, ATTN_IDLE);
}
void CEnvSpark::TimedSpark(void)
{
CreateSpark();
nextthink = time + (random() * m_flMaxDelay);
}
void CEnvSpark::Trigger(void)
{
if (spawnflags & EVSPARK_TOGGLE) {
if (think != __NULL__) {
think = __NULL__;
nextthink = 0;
} else {
think = TimedSpark;
nextthink = time + (random() * m_flMaxDelay);
}
} else {
CreateSpark();
}
}
void CEnvSpark::Respawn(void)
{
if (m_flMaxDelay <= 0) {
m_flMaxDelay = 1.0f;
}
if (spawnflags & EVSPARK_TOGGLE) {
if (spawnflags & EVSPARK_STARTON) {
think = TimedSpark;
nextthink = time + (random() * m_flMaxDelay);
}
}
}
CLASSEXPORT(env_spark, CEnvSpark)

View file

@ -0,0 +1,41 @@
/***
*
* 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/env_sprite_(Half-Life) */
enumflags {
ENVS_STARTON,
ENVS_PLAYONCE
};
class CEnvSprite : CBaseTrigger
{
void() CEnvSprite;
virtual void() Trigger;
};
void CEnvSprite::Trigger(void)
{
Respawn();
if (spawnflags & ENVS_PLAYONCE) {
}
}
void CEnvSprite::CEnvSprite(void)
{
CBaseTrigger::CBaseTrigger();
precache_model(m_oldModel);
Respawn();
if (!(spawnflags & ENVS_STARTON)) {
Hide();
}
}
CLASSEXPORT(env_sprite, CEnvSprite)

View file

@ -0,0 +1,123 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
/*
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).
*/
enumflags
{
SF_TRIGGER,
SF_TOUCH,
SF_PRESSURE
};
class CFuncBreakable : CBaseTrigger
{
float m_iMaterial;
virtual void() Trigger;
virtual void() touch;
virtual void( entity eAttacker, int iType, int iDamage ) vPain;
virtual void( entity eAttacker, int iType, int iDamage ) vDeath;
};
void CFuncBreakable :: Respawn ( void )
{
if ( spawnflags & SF_TRIGGER ) {
takedamage = DAMAGE_NO;
} else {
takedamage = DAMAGE_YES;
}
}
void CFuncBreakable :: vPain ( entity attacker, int type, int damage )
{
if (serverkeyfloat("*bspversion") != 30) {
return;
}
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 );
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;
}
}
void CFuncBreakable :: vDeath ( entity attacker, int type, int damage )
{
health = 0;
Effect_BreakModel( absmin, absmax, '0 0 0', m_iMaterial );
CBaseTrigger::UseTargets();
CBaseEntity::Hide();
}
void CFuncBreakable :: Trigger ( void )
{
CFuncBreakable::vDeath( world, 0, 0 );
}
void CFuncBreakable :: touch ( void )
{
if ( other.classname == classname ) {
return;
}
if ( m_iMaterial == MATERIAL_GLASS ) {
if (vlen(other.velocity) > 200) {
vDeath( other, 0, 1 );
}
}
}
void CFuncBreakable :: CFuncBreakable( void )
{
precache_model( model );
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_BSP;
setmodel( this, model );
CBaseEntity::CBaseEntity();
CFuncBreakable::Respawn();
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "material":
m_iMaterial = stoi( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !health ) {
health = 15;
}
}
CLASSEXPORT( func_breakable, CFuncBreakable )

View file

@ -0,0 +1,368 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define SF_BTT_NOMOVE 1
#define SF_BTT_TOGGLE 32
#define SF_BTT_SPARKS 64
#define SF_BTT_TOUCH_ONLY 256
enum
{
STATE_RAISED,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
enum
{
FRAME_OFF,
FRAME_ON
};
class CButton : CBaseTrigger
{
float m_flSpeed;
float m_flLip;
int m_iDamage;
int m_iState;
vector m_vecPos1;
vector m_vecPos2;
int m_iSounds;
float m_flNextTrigger;
vector m_vecDest;
string m_strNoise;
float m_flWait;
float m_flDelay;
virtual void() m_pMove = 0;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() MoveBack;
virtual void() MoveAway;
virtual void() Touch;
virtual void() Blocked;
virtual void() Trigger;
virtual void() PlayerUse;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
};
void CButton :: Precache( void )
{
precache_model( model );
switch( m_iSounds ) {
case 0:
m_strNoise = "common/null.wav";
break;
case 1:
m_strNoise = "buttons/button1.wav";
break;
case 2:
m_strNoise = "buttons/button2.wav";
break;
case 3:
m_strNoise = "buttons/button3.wav";
break;
case 4:
m_strNoise = "buttons/button4.wav";
break;
case 5:
m_strNoise = "buttons/button5.wav";
break;
case 6:
m_strNoise = "buttons/button6.wav";
break;
case 7:
m_strNoise = "buttons/button7.wav";
break;
case 8:
m_strNoise = "buttons/button8.wav";
break;
case 9:
m_strNoise = "buttons/button9.wav";
break;
case 10:
m_strNoise = "buttons/button10.wav";
break;
case 11:
m_strNoise = "buttons/button11.wav";
break;
case 12:
m_strNoise = "buttons/latchlocked1.wav";
break;
case 13:
m_strNoise = "buttons/latchunlocked1.wav";
break;
case 14:
m_strNoise = "buttons/lightswitch2.wav";
break;
case 21:
m_strNoise = "buttons/lever1.wav";
break;
case 22:
m_strNoise = "buttons/lever2.wav";
break;
case 23:
m_strNoise = "buttons/lever3.wav";
break;
case 24:
m_strNoise = "buttons/lever4.wav";
break;
case 25:
m_strNoise = "buttons/lever5.wav";
break;
default:
m_strNoise = "buttons/button9.wav";
}
precache_sound( m_strNoise );
}
void CButton :: Arrived( void )
{
m_iState = STATE_RAISED;
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = Touch;
}
if ( spawnflags & SF_BTT_TOGGLE ) {
return;
}
if ( m_flWait != -1 ) {
think = MoveBack;
nextthink = ( ltime + m_flWait );
}
}
void CButton :: Returned( void )
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = Touch;
}
m_iState = STATE_LOWERED;
frame = FRAME_OFF;
}
void CButton :: MoveBack( void )
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
if ( m_vecPos2 != m_vecPos1 ) {
CButton::MoveToDestination ( m_vecPos1, Returned );
} else {
CButton::Returned();
}
}
void CButton :: MoveAway( void )
{
if ( m_iState == STATE_UP ) {
return;
}
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
return;
}
m_iState = STATE_UP;
if ( m_vecPos2 != m_vecPos1 ) {
CButton::MoveToDestination( m_vecPos2, Arrived );
} else {
CButton::Arrived();
}
frame = FRAME_ON;
}
void CButton :: Trigger( void )
{
if ( m_flNextTrigger > time ) {
return;
}
m_flNextTrigger = time + m_flWait;
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ){
if ( m_flWait != -1 ) {
CButton::MoveBack();
}
return;
}
sound( this, CHAN_VOICE, m_strNoise, 1.0, ATTN_NORM );
CButton::MoveAway();
if ( m_flDelay ) {
#ifdef GS_DEVELOPER
dprint( sprintf( "CButton: Delayed trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
#ifdef GS_DEVELOPER
print( sprintf( "CButton: Normal trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets();
}
}
void CButton :: Touch( void )
{
if ( other.movetype == MOVETYPE_WALK ) {
CButton::Trigger();
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = __NULL__;
}
}
}
void CButton :: PlayerUse ( void )
{
Trigger();
}
void CButton :: Blocked( void )
{
if ( m_iDamage ) {
//Damage_Apply( other, this, dmg, other.origin, FALSE );
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
CButton::MoveAway ();
} else {
CButton::MoveBack ();
}
}
}
void CButton :: SetMovementDirection( void )
{
if ( angles == '0 -1 0' ) {
movedir = '0 0 1';
} else if ( angles == '0 -2 0' ) {
movedir = '0 0 -1';
} else {
makevectors( angles );
movedir = v_forward;
}
angles = '0 0 0';
}
void CButton :: MoveToDestination_End( void )
{
setorigin( this, m_vecDest );
velocity = '0 0 0';
nextthink = -1;
m_pMove();
}
void CButton :: 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." );
}
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 CButton :: CButton( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
break;
case "sounds":
m_iSounds = stoi( argv( i + 1 ) );
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CButton::Precache();
CButton::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;
}
CLASSEXPORT( func_button, CButton )

View file

@ -0,0 +1,88 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define SF_CONVEYOR_VISUAL 1
#define SF_CONVEYOR_NOTSOLID 2
class CFuncConveyor : CFuncWall
{
float m_flSpeed;
vector m_vecMoveDir;
void() CFuncConveyor;
virtual void() Trigger;
virtual void() touch;
virtual void() SetMovementDirection;
virtual void( float ) UpdateSpeed;
};
void CFuncConveyor :: 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';
}
// HACKHACK -- This is ugly, but encode the speed in the rendercolor to avoid adding more data to the network stream
void CFuncConveyor :: UpdateSpeed( float flSpeed )
{
// Encode it as an integer with 4 fractional bits
/*int speedCode = (int)( fabs( flSpeed ) * 16.0f );
if ( flSpeed < 0 ) {
pev->rendercolor.x = 1;
} else {
pev->rendercolor.x = 0;
}
pev->rendercolor.y = (speedCode >> 8);
pev->rendercolor.z = (speedCode & 0xFF);*/
}
void CFuncConveyor :: touch ( void )
{
//other.basevelocity = m_vecMoveDir * m_flSpeed;
}
void CFuncConveyor :: Trigger ( void )
{
m_flSpeed = -m_flSpeed;
UpdateSpeed( m_flSpeed );
}
void CFuncConveyor :: CFuncConveyor ( void )
{
SetMovementDirection();
CFuncWall::CFuncWall();
if ( !( spawnflags & SF_CONVEYOR_VISUAL ) ) {
//SetBits( pev->flags, FL_CONVEYOR );
}
// HACKHACK - This is to allow for some special effects
if ( spawnflags & SF_CONVEYOR_NOTSOLID ) {
solid = SOLID_NOT;
skin = 0;
}
if ( m_flSpeed == 0 ) {
m_flSpeed = 100;
}
UpdateSpeed( m_flSpeed );
}
CLASSEXPORT( func_conveyor, CFuncConveyor )

View file

@ -0,0 +1,361 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// 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
};
class CFuncDoor : CBaseTrigger
{
vector m_vecPos1;
vector m_vecPos2;
vector m_vecDest;
vector m_vecMoveDir;
float m_flSpeed;
float m_flLip;
float m_iState;
float m_flNextTrigger;
float m_flWait;
float m_flDelay;
int m_iMoveSnd;
int m_iStopSnd;
int m_iDamage;
int m_iLocked;
void() CFuncDoor;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
virtual void() MoveAway;
virtual void() MoveBack;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() Trigger;
virtual void() Blocked;
virtual void() Touch;
virtual void() PlayerUse;
virtual void() m_pMove = 0;
};
void CFuncDoor :: Precache ( void )
{
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
precache_sound( sprintf( "doors/doormove%i.wav", m_iMoveSnd ) );
} else {
precache_sound( "common/null.wav" );
}
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
precache_sound( sprintf( "doors/doorstop%i.wav", m_iStopSnd ) );
} else {
precache_sound( "common/null.wav" );
}
}
void CFuncDoor :: PlayerUse ( void )
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
}
void CFuncDoor :: Arrived ( void )
{
m_iState = STATE_RAISED;
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%i.wav", m_iStopSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = Touch;
}
if ( m_flWait < 0 ) {
return;
}
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
think = MoveBack;
nextthink = ( ltime + m_flWait );
}
}
void CFuncDoor :: Returned ( void )
{
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%i.wav", m_iStopSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = Touch;
}
m_iState = STATE_LOWERED;
}
void CFuncDoor :: MoveBack ( void )
{
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
MoveToDestination( m_vecPos1, Returned );
}
void CFuncDoor :: MoveAway ( void )
{
if ( m_iState == STATE_UP ) {
return;
}
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
return;
}
}
m_iState = STATE_UP;
MoveToDestination( m_vecPos2, Arrived );
}
void CFuncDoor :: Trigger ( void )
{
if ( m_flNextTrigger > ltime ) {
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
return;
}
}
m_flNextTrigger = ltime + m_flWait;
// Only trigger stuff when we are done moving
if ( ( m_iState == STATE_RAISED ) || ( m_iState == STATE_LOWERED ) ) {
if ( m_flDelay > 0 ) {
#ifdef GS_DEVELOPER
print( sprintf( "CFuncDoor: Delayed trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
#ifdef GS_DEVELOPER
dprint( sprintf( "CFuncDoor: Normal trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets();
}
}
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ){
MoveBack();
return;
}
MoveAway();
}
void CFuncDoor :: Touch ( void )
{
if ( spawnflags & SF_MOV_TOGGLE ) {
return;
}
if ( m_iLocked ) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin[2] <= maxs[2] - 2 ) {
Trigger();
}
}
}
void CFuncDoor :: Blocked ( void )
{
if( m_iDamage ) {
//Damage_Apply( other, self, dmg, other.origin, FALSE );
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
MoveAway ();
} else {
MoveBack ();
}
}
}
void CFuncDoor :: Respawn ( void )
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
blocked = Blocked;
//Use = Trigger;
if ( m_flWait == -1 ) {
spawnflags |= SF_MOV_TOGGLE;
}
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( !m_iDamage ) {
m_iDamage = 2;
}
if ( spawnflags & SF_MOV_USE ) {
touch = __NULL__;
gflags |= GF_USABLE;
} else {
touch = Touch;
gflags -= gflags & GF_USABLE;
}
m_iState = STATE_LOWERED;
m_vecPos1 = origin;
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;
}
}
void CFuncDoor :: CFuncDoor ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
break;
case "movesnd":
m_iMoveSnd = stoi( argv( i + 1 ) );
break;
case "stopsnd":
m_iStopSnd = stoi( argv( i + 1 ) );
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CFuncDoor::Precache();
CFuncDoor::SetMovementDirection();
CFuncDoor::Respawn();
CBaseTrigger::CBaseTrigger();
if ( m_strTargetName ) {
m_iLocked = TRUE;
}
}
void CFuncDoor :: 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 CFuncDoor :: MoveToDestination_End ( void )
{
setorigin( this, m_vecDest );
velocity = '0 0 0';
nextthink = -1;
m_pMove();
}
void CFuncDoor :: 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." );
}
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 ) );
}
CLASSEXPORT( func_door, CFuncDoor )
void func_water ( void )
{
spawnfunc_CFuncDoor();
self.classname = "CFuncWater";
self.solid = SOLID_BSP;
self.skin = CONTENT_WATER;
}

View file

@ -0,0 +1,331 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define SF_ROT_YAXIS 0
#define SF_ROT_OPEN 1
#define SF_ROT_BACKWARDS 2
#define SF_ROT_PASSABLE 8
#define SF_ROT_ONEWAY 16
#define SF_ROT_TOGGLE 32
#define SF_ROT_ZAXIS 64
#define SF_ROT_XAXIS 128
#define SF_ROT_USE 256
#define SF_DOOR_NOMONSTERS 512
#define SF_DOOR_SILENT 0x80000000i
class CDoorRotating : CBaseTrigger
{
int m_iMoveSnd;
int m_iStopSnd;
int m_iDamage;
float m_flDistance;
float m_flSpeed;
float m_flLip;
float m_iState;
float m_flNextAction;
float m_flWait;
float m_flDelay;
vector m_vecDest;
vector m_vecPos1;
vector m_vecPos2;
vector m_vecMoveDir;
virtual void() m_pMove = 0;
void() CDoorRotating;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() RotateBack;
virtual void() RotateAway;
virtual void() Trigger;
virtual void() PlayerUse;
virtual void() Touch;
virtual void() Blocked;
virtual void() SetMovementDirection;
virtual void( vector angle, void() func ) RotateToDestination;
virtual void() RotateToDestination_End;
};
void CDoorRotating :: Precache ( void )
{
if ( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
precache_sound( sprintf( "doors/doormove%i.wav", m_iMoveSnd ) );
} else {
precache_sound( "common/null.wav" );
}
if ( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
precache_sound( sprintf( "doors/doorstop%i.wav", m_iStopSnd ) );
} else {
precache_sound( "common/null.wav" );
}
}
void CDoorRotating :: 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 );
} else {
sound( this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !(spawnflags & SF_ROT_USE) ) {
touch = Touch;
}
if ( m_flWait < 0 ) {
return;
}
think = RotateBack;
nextthink = ( ltime + m_flWait );
}
void CDoorRotating :: Returned ( void )
{
if ( !(spawnflags & SF_ROT_USE) ) {
touch = Touch;
}
m_iState = STATE_LOWERED;
}
void CDoorRotating :: RotateBack ( void )
{
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 );
}
if ( !(spawnflags & SF_ROT_USE) ) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
RotateToDestination( m_vecPos1, Returned );
}
void CDoorRotating :: RotateAway ( void )
{
float fDirection = 1.0;
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 );
} else {
sound( this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
return;
}
m_iState = STATE_UP;
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;
if ( ( ( vDifference[0] * vNext[1] ) - ( vDifference[1] * vNext[0] ) ) < 0 ) {
fDirection = -1.0f;
}
}
RotateToDestination( m_vecPos2 * fDirection, Arrived );
}
void CDoorRotating :: Trigger ( void )
{
if ( m_flNextAction > time ) {
return;
}
m_flNextAction = time + m_flWait;
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ) {
RotateBack();
return;
}
RotateAway();
if ( m_flDelay ) {
#ifdef GS_DEVELOPER
print( sprintf( "CDoorRotating: Delayed trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
#ifdef GS_DEVELOPER
print( sprintf( "CDoorRotating: Normal trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets();
}
}
void CDoorRotating :: PlayerUse ( void )
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
}
void CDoorRotating :: Touch ( void )
{
if ( spawnflags & SF_ROT_USE ) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin[2] <= maxs[2] - 2 ) {
eActivator = other;
Trigger();
}
}
touch = __NULL__;
}
void CDoorRotating :: Blocked ( void )
{
if ( m_iDamage ) {
// Damage_Apply( other, this, m_iDamage, other.origin, FALSE );
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
RotateAway ();
} else {
RotateBack ();
}
}
}
void CDoorRotating :: 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 CDoorRotating :: SetMovementDirection ( void )
{
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';
}
}
void CDoorRotating :: RotateToDestination_End ( void )
{
angles = m_vecDest;
avelocity = '0 0 0';
nextthink = -1;
m_pMove();
}
void CDoorRotating :: RotateToDestination ( vector vDestinationAngle, void() func )
{
vector vecAngleDifference;
float flTravelLength, flTravelTime;
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 ) );
m_vecDest = vDestinationAngle;
m_pMove = func;
think = RotateToDestination_End;
nextthink = ( ltime + flTravelTime );
}
void CDoorRotating :: CDoorRotating ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
break;
case "movesnd":
m_iMoveSnd = stoi( argv( i + 1 ) );
break;
case "stopsnd":
m_iStopSnd = stoi( argv( i + 1 ) );
break;
case "distance":
m_flDistance = stof( argv( i + 1 ) );
break;
case "delay":
m_flDelay = stof( 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;
}
CDoorRotating::Precache();
CBaseEntity::CBaseEntity();
CDoorRotating::SetMovementDirection();
CDoorRotating::Respawn();
}
CLASSEXPORT( func_door_rotating, CDoorRotating )

View file

@ -0,0 +1,38 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CFuncHealthCharger:CBaseTrigger
{
float m_flDelay;
void() CFuncHealthCharger;
virtual void() PlayerUse;
};
void CFuncHealthCharger::PlayerUse(void)
{
eActivator.flags = (eActivator.flags - FL_USERELEASED);
if (m_flDelay > time) {
return;
}
eActivator.health = bound(0, eActivator.health += 15, 100);
m_flDelay = time + 1.0f;
}
void CFuncHealthCharger::CFuncHealthCharger(void)
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
gflags = GF_USABLE;
}
CLASSEXPORT(func_healthcharger, CFuncHealthCharger)

View file

@ -0,0 +1,29 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CFuncIllusionary : CBaseEntity
{
virtual void() Use;
};
void CFuncIllusionary :: CFuncIllusionary ( void )
{
precache_model( model );
//angles = '0 0 0';
movetype = MOVETYPE_PUSH;
self.solid = SOLID_NOT;
setmodel( this, model );
CBaseEntity::CBaseEntity();
}
void CFuncIllusionary :: Use ( void )
{
skin = 1 - skin;
}
CLASSEXPORT( func_illusionary, CFuncIllusionary )

View file

@ -0,0 +1,21 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CFuncLadder : CBaseEntity {
void() CFuncLadder;
};
void CFuncLadder :: CFuncLadder ( void )
{
setmodel( this, model );
movetype = MOVETYPE_NONE;
skin = CONTENT_LADDER;
solid = SOLID_BSP;
}
CLASSEXPORT( func_ladder, CFuncLadder )

View file

@ -0,0 +1,38 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CFuncSuitCharger:CBaseTrigger
{
float m_flDelay;
void() CFuncSuitCharger;
virtual void() PlayerUse;
};
void CFuncSuitCharger::PlayerUse(void)
{
eActivator.flags = (eActivator.flags - FL_USERELEASED);
if (m_flDelay > time) {
return;
}
eActivator.armor = bound(0, eActivator.armor += 15, 100);
m_flDelay = time + 1.0f;
}
void CFuncSuitCharger::CFuncSuitCharger(void)
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
gflags = GF_USABLE;
}
CLASSEXPORT(func_recharge, CFuncSuitCharger)

View file

@ -0,0 +1,113 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags
{
FR_STARTON,
FR_REVERSE,
FR_ZAXIS,
FR_XAXIS,
FR_ACCDCC,
FR_FANPAIN,
FR_NOTSOLID,
FR_SMALLRADIUS,
FR_MRADIUS,
FR_LRADIUS
};
class CFuncRotating : CBaseTrigger
{
vector m_vecMoveDir;
float m_flSpeed;
void() CFuncRotating;
virtual void() Respawn;
virtual void() Trigger;
virtual void() Rotate;
virtual void() SetMovementDirection;
};
void CFuncRotating :: Rotate( void )
{
nextthink = ltime + 10.0f;
}
void CFuncRotating :: Trigger ( void )
{
if ( vlen( avelocity ) ) {
avelocity = '0 0 0';
} else {
avelocity = m_vecMoveDir * m_flSpeed;
}
}
void CFuncRotating :: Blocked ( void )
{
if ( spawnflags & FR_FANPAIN ) {
// Damage_Apply( other, this, m_iDamage, other.origin, FALSE );
}
}
void CFuncRotating :: Respawn ( void )
{
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
if ( spawnflags & FR_NOTSOLID ) {
solid = SOLID_NOT;
} else {
solid = SOLID_BSP;
}
if ( spawnflags & FR_STARTON ) {
avelocity = m_vecMoveDir * m_flSpeed;
think = Rotate;
nextthink = ltime + 1.5f;
}
}
void CFuncRotating :: SetMovementDirection ( void )
{
if ( spawnflags & FR_ZAXIS ) {
m_vecMoveDir = '0 0 1';
} else if ( spawnflags & FR_XAXIS ) {
m_vecMoveDir = '1 0 0';
} else {
m_vecMoveDir = '0 1 0';
}
if ( spawnflags & FR_REVERSE ) {
m_vecMoveDir *= -1;
}
}
void CFuncRotating :: CFuncRotating ( void )
{
precache_model( model );
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
/*case "spawnorigin":
setorigin( this, stov( argv( i + 1 ) ) );
break;*/
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
CBaseTrigger::CBaseTrigger();
CFuncRotating::SetMovementDirection();
CFuncRotating::Respawn();
}
CLASSEXPORT( func_rotating, CFuncRotating )

View file

@ -0,0 +1,194 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
/*class CPathCorner
{
float m_flSpeed;
float m_flWait;
string m_strTarget;
void() CPathCorner;
};
void CPathCorner :: CPathCorner ( void )
{
m_flSpeed = 100;
m_flWait = 1.0f;
}
CLASSEXPORT(path_corner, CPathCorner)
class CFuncTrain
{
int m_iDamage;
float m_flNextBlockAttack;
float m_flTraveltime;
float m_flWait;
float m_flSpeed;
vector m_vecDestination;
vector m_vecDestDelta;
// We don't need to inherit CBaseTrigger for these yet
string m_strTarget;
entity m_eTarget;
void() CFuncTrain;
virtual void() Move;
virtual void() Blocked;
virtual void() Trigger;
virtual void() Find;
virtual void() Trigger;
virtual void() Wait;
virtual void() Next;
virtual void() m_pMove = 0;
};
void CFuncTrain :: Done ( void )
{
setorigin( this, m_vecDestination );
velocity = '0 0 0';
nextthink = -1;
if ( m_pMove ) {
m_pMove();
}
}
void CFuncTrain :: Blocked ( void )
{
if ( time < m_flNextBlockAttack ) {
return;
}
m_flNextBlockAttack = time + 0.5;
//other.deathtype = "squish";
//T_Damage (other, self, self, m_iDamage);
}
void CFuncTrain :: Trigger ( void )
{
// already activated
if ( think != Find ) {
return;
}
Next();
}
void CFuncTrain :: Wait ( void )
{
if ( m_flWait ) {
nextthink = ltime + m_flWait;
sound (self, CHAN_VOICE, noise, 1, ATTN_NORM);
} else {
nextthink = ltime + 0.1f;
}
think = Next;
}
void CFuncTrain :: Next ( void )
{
float flLen;
CPathCorner pTarget;
m_eTarget = find( world, ::targetname, m_strTarget );
pTarget = (CPathCorner) m_eTarget;
m_strTarget = pTarget.m_strTarget;
if ( !m_strTarget ) {
objerror( "train_next: no next target" );
}
if ( pTarget.m_flWait ) {
m_flWait = pTarget.m_flWait;
} else {
m_flWait = 0;
}
sound( self, CHAN_VOICE, noise1, 1, ATTN_NORM );
m_vecDestination = pTarget.origin - mins;
m_flSpeed = pTarget.m_flSpeed;
m_pMove = Wait;
think = Done;
if ( m_vecDestination == origin ) {
velocity = '0 0 0';
nextthink = ltime + 0.1;
return;
}
// set destdelta to the vector needed to move
m_vecDestDelta = m_vecDestination - origin;
flLen = vlen( m_vecDestDelta ); // calculate length of vector
m_flTraveltime = flLen / m_flSpeed; // divide by speed to get time to reach dest
if ( m_flTraveltime < 0.1 ) {
velocity = '0 0 0';
nextthink = ltime + 0.1;
return;
}
nextthink = ltime + m_flTraveltime; // set nextthink to trigger a think when dest is reached
velocity = m_vecDestDelta * ( 1 / m_flTraveltime ); // scale the destdelta vector by the time spent traveling to get velocity
}
void CFuncTrain :: Find ( void )
{
CPathCorner pTarget;
m_eTarget = find(world, ::targetname, m_strTarget);
pTarget = (CPathCorner) m_eTarget;
m_strTarget = pTarget.m_strTarget;
setorigin (this, m_eTarget.origin - mins);
// not triggered, so start immediately
if ( !targetname ) {
nextthink = ltime + 0.1;
think = Next;
}
}
void CFuncTrain :: CFuncTrain ( void )
{
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( !m_strTarget ) {
objerror ("func_train without a target");
}
if ( !m_iDamage ) {
m_iDamage = 2;
}
if ( sounds == 0 ) {
noise = ("misc/null.wav");
precache_sound ("misc/null.wav");
noise1 = ("misc/null.wav");
precache_sound ("misc/null.wav");
}
if ( sounds == 1 ) {
noise = ("plats/train2.wav");
precache_sound ("plats/train2.wav");
noise1 = ("plats/train1.wav");
precache_sound ("plats/train1.wav");
}
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
blocked = Blocked;
setmodel( this, model );
setsize( this, mins , maxs );
setorigin( this, origin );
// start trains on the second frame, to make sure their targets have had
// a chance to spawn
nextthink = ltime + 0.1;
think = Find;
}
CLASSEXPORT(func_train, CFuncTrain)*/

View file

@ -0,0 +1,31 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CFuncWall : CBaseTrigger
{
void() CFuncWall;
virtual void() Trigger;
};
void CFuncWall :: CFuncWall ( void )
{
precache_model( model );
//angles = '0 0 0';
movetype = MOVETYPE_PUSH;
solid = SOLID_BSP;
setmodel( this, model );
CBaseTrigger::CBaseTrigger();
}
void CFuncWall :: Trigger ( void )
{
frame = 1 - frame;
}
CLASSEXPORT( func_wall, CFuncWall )
CLASSEXPORT( func_train, CFuncWall )

View file

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

View file

@ -0,0 +1,18 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CStartDM
{
void(void) CStartDM;
};
void CStartDM::CStartDM(void)
{
}
CLASSEXPORT( info_player_deathmatch, CStartDM )

View file

@ -0,0 +1,15 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CStartOBS
{
};
CLASSEXPORT( info_player_spectator, CStartOBS )
CLASSEXPORT( info_player_spectate, CStartOBS )

View file

@ -0,0 +1,18 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CStartSP
{
void(void) CStartSP;
};
void CStartSP::CStartSP(void)
{
}
CLASSEXPORT( info_player_start, CStartSP )

View file

@ -0,0 +1,61 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CItemFood
{
int m_iIsCan;
void() CItemFood;
virtual void() Setup;
virtual void() Touch;
};
void CItemFood :: Touch ( void )
{
if ( other.classname != "Player" ) {
return;
}
if ( owner != __NULL__ ) {
CEnvBeverage bevOwner = (CEnvBeverage)owner;
bevOwner.m_iReady = TRUE;
}
solid = SOLID_NOT;
remove( this );
}
void CItemFood :: Setup ( void )
{
solid = SOLID_TRIGGER;
setsize( this, '-8 -8 -8', '8 8 8' );
touch = Touch;
if ( m_iIsCan ) {
sound( this, CHAN_ITEM, "weapons/g_bounce3.wav", 1.0f, ATTN_NORM );
}
}
void CItemFood :: CItemFood ( void )
{
// TODO: differentiate between item_sodacan and item_food
m_iIsCan = 1;
solid = SOLID_NOT;
movetype = MOVETYPE_TOSS;
if ( m_iIsCan ) {
setmodel( this, "models/can.mdl" );
}
setsize( this, '0 0 0', '0 0 0' );
think = Setup;
nextthink = time + 1.0f;
}
CLASSEXPORT( item_sodacan, CItemFood )
CLASSEXPORT( item_food, CItemFood )

View file

@ -0,0 +1,30 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CItemSuit:CBaseTrigger
{
void() CItemSuit;
virtual void() touch;
};
void CItemSuit::touch(void)
{
Trigger();
Hide();
}
void CItemSuit::CItemSuit(void)
{
CBaseTrigger::CBaseTrigger();
precache_model("models/w_kevlar.mdl");
setmodel( self, "models/w_kevlar.mdl");
InitPointTrigger();
}
CLASSEXPORT(item_suit, CItemSuit)

View file

@ -0,0 +1,66 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CLight : CBaseTrigger
{
string m_strPattern;
int m_iEnabled;
float m_flStyle;
void() CLight;
virtual void() Trigger;
};
void CLight :: Trigger ( void )
{
if ( m_iEnabled == TRUE ) {
//dprint( "CLight: Turned off!\n" );
lightstyle( m_flStyle, "a" );
m_iEnabled = FALSE;
} else {
//dprint( "CLight: Turned on!\n" );
lightstyle( m_flStyle, m_strPattern );
m_iEnabled = TRUE;
}
}
void CLight :: CLight ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "pattern":
m_strPattern = argv( i + 1 );
break;
case "style":
m_flStyle = stof( argv( i + 1 ) );
style = __NULL__;
break;
default:
break;
}
}
/*if ( !m_strPattern ) {
m_strPattern = getlightstyle( m_flStyle );
}*/
if ( !m_strPattern ) {
m_strPattern = "m";
}
if ( spawnflags & 1 ) {
lightstyle( m_flStyle, "a" );
m_iEnabled = FALSE;
} else {
lightstyle( m_flStyle, m_strPattern );
m_iEnabled = TRUE;
}
}
CLASSEXPORT( light, CLight )
CLASSEXPORT( light_spot, CLight )

View file

@ -0,0 +1,41 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags
{
MF_WAITTILSEEN,
MF_GAG,
MF_MONSTERCLIP,
MF_PRISONER,
MF_UNUSED,
MF_WAITFORSCRIPT,
MF_PREDISASTER,
MF_FADECORPSE
};
class CMonsterFurniture : CBaseEntity
{
void() CMonsterFurniture;
//virtual void() Respawn;
};
void CMonsterFurniture :: CMonsterFurniture ( void )
{
precache_model( model );
setmodel( this, model );
CBaseEntity::CBaseEntity();
#if 1
self.movetype = MOVETYPE_NOCLIP;
self.solid = SOLID_NOT;
//self.avelocity = '0 90 0 ';
//self.modelflags = MF_ROTATE;
#endif
}
CLASSEXPORT( monster_furniture, CMonsterFurniture )

View file

@ -0,0 +1,51 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
enumflags
{
MF_WAITTILLSEEN,
MF_GAG,
MF_MONSTERCLIP,
MF_PRISONER,
MF_UNUSED,
MF_WAITFORSCRIPT,
MF_PREDISASTER,
MF_FADECORPSE
};
class CMonsterGeneric : CBaseEntity
{
void() CMonsterGeneric;
//virtual void() Respawn;
};
void CMonsterGeneric :: CMonsterGeneric ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "sequence":
frame = stof( argv( i + 1 ) );
break;
default:
break;
}
}
precache_model( model );
setmodel( this, model );
CBaseEntity::CBaseEntity();
#if 0
self.movetype = MOVETYPE_NOCLIP;
self.solid = SOLID_NOT;
self.avelocity = '0 90 0 ';
self.modelflags = MF_ROTATE;
#endif
}
CLASSEXPORT( monster_generic, CMonsterGeneric )

View file

@ -0,0 +1,71 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CMultiManager : CBaseTrigger
{
string m_strBuffer;
int m_iBusy;
virtual void() Trigger;
};
void CMultiManager :: Trigger ( void )
{
static void mm_enttrigger ( void ) {
spawnfunc_CBaseTrigger();
CBaseTrigger wow = (CBaseTrigger) self;
wow.m_strTarget = wow.netname;
entity eFind = find( world, CBaseTrigger::m_strTargetName, self.netname );
//dprint( sprintf( "CMultiManager: %s (%s)\n", wow.m_strTarget, eFind.classname ) );
CBaseTrigger::UseTargets();
remove( wow );
}
int iFields = tokenizebyseparator( m_strBuffer, " " );
for ( int i = 0; i < iFields; i+=2 ) {
// HACK: Avoid infinite loops
if ( m_strTargetName != argv( i ) ) {
entity eTemp = spawn();
eTemp.netname = argv( i );
eTemp.think = mm_enttrigger;
eTemp.nextthink = time + stof( argv( i + 1 ) );
}
}
}
void CMultiManager :: CMultiManager ( void )
{
m_strBuffer = "";
int iFields = tokenize( __fullspawndata );
for ( int i = 1; i < ( iFields - 1 ); i += 2 ) {
// Sigh, let's attempt to sanitize this
switch ( argv( i ) ) {
case "{":
case "}":
case "classname":
case "origin":
case "targetname":
case "spawnflags":
continue;
break;
default:
if ( substring( argv( i ), strlen( argv( i ) ) - 3, 1 ) == "#" ) {
m_strBuffer = sprintf( "%s%s %s ", m_strBuffer, substring( argv( i ), 0, strlen( argv( i ) ) - 3 ), argv( i + 1 ) );
} else if ( substring( argv( i ), strlen( argv( i ) ) - 2, 1 ) == "#" ) {
m_strBuffer = sprintf( "%s%s %s ", m_strBuffer, substring( argv( i ), 0, strlen( argv( i ) ) - 2 ), argv( i + 1 ) );
} else {
m_strBuffer = sprintf( "%s%s %s ", m_strBuffer, argv( i ), argv( i + 1 ) );
}
}
}
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT( multi_manager, CMultiManager )

View file

@ -0,0 +1,46 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CMultiSource : CBaseTrigger
{
void() CMultiSource;
virtual int() GetValue;
virtual void() Trigger;
};
int CMultiSource :: GetValue ( void )
{
int iWillTrigger = TRUE;
for ( entity eTemp = world; ( eTemp = find( eTemp, CBaseTrigger::m_strTarget, m_strTargetName ) ); ) {
CBaseTrigger tTemp = (CBaseTrigger) eTemp;
if ( tTemp.GetValue() == FALSE ) {
iWillTrigger = FALSE;
break;
}
}
return iWillTrigger;
}
void CMultiSource :: Trigger ( void )
{
if ( GetValue() == FALSE ) {
return;
}
//dprint( sprintf( "CMultiSource: Trigger of %s\n", m_strTarget ) );
CBaseTrigger::UseTargets();
}
void CMultiSource :: CMultiSource ( void )
{
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT( multisource, CMultiSource )

View file

@ -0,0 +1,57 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CInfoNull
{
void() CInfoNull;
};
void CInfoNull :: CInfoNull ( void )
{
remove( self );
}
class CInfoNotNull
{
void() CInfoNotNull;
};
void CInfoNotNull :: CInfoNotNull ( void )
{
}
CLASSEXPORT( info_null, CInfoNull )
CLASSEXPORT( info_notnull, CInfoNotNull )
CLASSEXPORT( info_node, CInfoNotNull )
CLASSEXPORT( info_target, CInfoNotNull )
/*class CSuit : CBaseTrigger
{
void CSuit;
virtual void() Trigger;
};
void CSuit :: Trigger ( void )
{
CBaseTrigger::UseTargets();
remove( self );
}
void CSuit :: CSuit ( void )
{
CBaseTrigger::CBaseTrigger();
solid = SOLID_TRIGGER;
model = "models/w_suit.mdl";
precache_model( model );
setmodel( this, model );
touch = Trigger;
}
SPAWNEXPORT item_suit ( void ) { spawnfunc_CSuit(); }
SPAWNEXPORT world_items ( void ) { spawnfunc_CSuit(); }*/

View file

@ -0,0 +1,44 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerAuto : CBaseTrigger
{
float m_flDelay;
void() CTriggerAuto;
virtual void() think;
};
void CTriggerAuto :: think ( void )
{
// This is weird, because ents may not be spawned yet.
// However, Half-Life doesn't care about this, either.
// So why should we?
CBaseTrigger::UseTargets_Delay( m_flDelay );
if ( spawnflags & 1 ) {
remove( this );
}
}
void CTriggerAuto :: CTriggerAuto ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
nextthink = time + 0.2f;
}
CLASSEXPORT( trigger_auto, CTriggerAuto )

View file

@ -0,0 +1,43 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerCamera:CBaseTrigger
{
float m_flWait;
void() CTriggerCamera;
virtual void() Trigger;
};
void CTriggerCamera::Trigger(void)
{
if (m_strTarget) {
entity e = find(world, CBaseTrigger::m_strTargetName, m_strTarget);
if (e) {
angles = vectoangles(e.origin - origin);
angles_x *= -1;
}
}
Client_TriggerCamera(eActivator, origin, angles, m_flWait);
}
void CTriggerCamera::CTriggerCamera(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "wait":
m_flWait = stof(argv(i + 1));
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
}
CLASSEXPORT(trigger_camera, CTriggerCamera)

View file

@ -0,0 +1,40 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerCDAudio : CBaseTrigger
{
int m_iCDTrack;
void() CTriggerCDAudio;
virtual void() Trigger;
};
void CTriggerCDAudio :: Trigger ( void )
{
//dprint( sprintf( "CTriggerCDAudio: Now playing CD track %i", m_iCDTrack ) );
WriteByte( MSG_ALL, 32 ); // aka SVC_CDTRACK
WriteByte( MSG_ALL, m_iCDTrack );
remove( this );
}
void CTriggerCDAudio :: CTriggerCDAudio ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "health":
m_iCDTrack = stoi( argv( i + 1 ) );
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
CBaseTrigger::InitBrushTrigger();
touch = Trigger;
}
CLASSEXPORT( trigger_cdaudio, CTriggerCDAudio )

View file

@ -0,0 +1,108 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
vector g_landmarkpos;
enumflags {
LC_NOINTERMISSION, // Unused?
LC_USEONLY
};
class CLevelChanger : CBaseTrigger
{
string m_strMap;
string m_strLandmark;
float m_flChangeDelay;
entity m_activator;
void() CLevelChanger;
virtual void() Change;
virtual void() Trigger;
virtual int( entity, entity ) IsInside;
};
int CLevelChanger :: IsInside ( entity ePlayer, entity eVolume ) {
if ( ePlayer.absmin[0] > eVolume.absmax[0] ||
ePlayer.absmin[1] > eVolume.absmax[1] ||
ePlayer.absmin[2] > eVolume.absmax[2] ||
ePlayer.absmax[0] < eVolume.absmin[0] ||
ePlayer.absmax[1] < eVolume.absmin[1] ||
ePlayer.absmax[2] < eVolume.absmin[2] )
return FALSE;
return TRUE;
}
void CLevelChanger :: Change ( void )
{
if ( m_strLandmark ) {
entity landmark = find( world, ::targetname, m_strLandmark );
g_landmarkpos = landmark.origin - m_activator.origin;
changelevel( m_strMap, m_strLandmark );
} else {
changelevel( m_strMap );
}
}
void CLevelChanger :: Trigger ( void )
{
//entity eVolume;
if ( time < 5 ) {
return;
}
/*eVolume = find( world, ::targetname, m_strLandmark );
if ( eVolume && eVolume.classname == "CTriggerVolume" ) {
if ( IsInside( other, eVolume ) == FALSE ) {
return;
}
}*/
m_activator = other;
if ( m_flChangeDelay ) {
think = Change;
nextthink = time + m_flChangeDelay;
} else {
Change();
}
}
void CLevelChanger :: CLevelChanger ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "map":
m_strMap = argv( i + 1 );
break;
case "landmark":
m_strLandmark = argv( i + 1 );
break;
case "changedelay":
m_flChangeDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
if ( !( spawnflags & LC_USEONLY ) ) {
touch = Trigger;
}
CBaseTrigger::InitBrushTrigger();
}
CLASSEXPORT( info_landmark, CInfoNull )
CLASSEXPORT( trigger_changelevel, CLevelChanger )
vector Landmark_GetSpot(void)
{
entity landmark = find(world, targetname, startspot);
return landmark.origin + g_landmarkpos;
}

View file

@ -0,0 +1,19 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerEnd : CBaseTrigger
{
virtual void() Trigger;
}
void CTriggerEnd :: Trigger ( void )
{
localcmd( "disconnect\n" );
}
CLASSEXPORT( trigger_endsection, CTriggerEnd )

View file

@ -0,0 +1,100 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define SF_HURT_ONCE 1 // Turn off once it fired the first time
#define SF_HURT_OFF 2 // Needs to be triggered in order to work again
#define SF_HURT_NOPLAYERS 8 // Don't hurt players
#define SF_HURT_FIREONPLAYER 16 // Only call UseTarget functions when it's a player
#define SF_HURT_TOUCHPLAYER 32 // Only hurt players
class CTriggerHurt : CBaseTrigger
{
float m_flNextTrigger;
int m_iDamage;
float m_flDelay;
void() CTriggerHurt;
};
void CTriggerHurt :: Trigger ( void )
{
if ( solid == SOLID_NOT ) {
solid = SOLID_TRIGGER;
} else {
solid = SOLID_NOT;
}
}
void CTriggerHurt :: Touch ( void )
{
if ( m_flNextTrigger > ltime ) {
return;
} else if ( other.takedamage == DAMAGE_NO ) {
return;
} else if ( ( spawnflags & SF_HURT_TOUCHPLAYER ) && !( other.flags & FL_CLIENT ) ) {
return;
} else if ( ( spawnflags & SF_HURT_NOPLAYERS ) && ( other.flags & FL_CLIENT ) ) {
return;
}
if ( spawnflags & SF_HURT_FIREONPLAYER ) {
if ( other.flags & FL_CLIENT ) {
if ( m_flDelay > 0 ) {
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
CBaseTrigger::UseTargets();
}
}
} else {
if ( m_flDelay > 0 ) {
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
CBaseTrigger::UseTargets();
}
}
// Damage_Apply( other, this, m_iDamage, other.origin, FALSE );
//Damage_Apply( other, world, m_iDamage, DAMAGE_BLEED, WEAPON_NONE );
// Shut it down if used once
if ( spawnflags & SF_HURT_ONCE ) {
solid = SOLID_NOT;
}
m_flNextTrigger = ltime + 0.5;
}
void CTriggerHurt :: Respawn ( void )
{
solid = SOLID_TRIGGER;
if ( spawnflags & SF_HURT_OFF ) {
solid = SOLID_NOT;
}
touch = Touch;
}
void CTriggerHurt :: CTriggerHurt ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "dmg":
m_iDamage = stoi( argv( i + 1 ) );
break;
case "wait":
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CBaseTrigger::InitBrushTrigger();
CTriggerHurt::Respawn();
CBaseEntity::CBaseEntity();
}
CLASSEXPORT( trigger_hurt, CTriggerHurt )

View file

@ -0,0 +1,69 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// TODO: These are missing
enumflags
{
TM_MONSTERS,
TM_NOCLIENTS,
TM_PUSHABLES
};
class CTriggerMultiple : CBaseTrigger
{
float m_flDelay;
float m_flWait;
void() CTriggerMultiple;
virtual void() touch;
virtual void() Respawn;
};
void CTriggerMultiple :: touch ( void )
{
if ( m_flDelay > 0 ) {
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
CBaseTrigger::UseTargets();
}
think = Respawn;
nextthink = time + m_flWait;
solid = SOLID_NOT;
#ifdef GS_DEVELOPER
alpha = 0.001f;
#endif
}
void CTriggerMultiple :: Respawn ( void )
{
solid = SOLID_TRIGGER;
#ifdef GS_DEVELOPER
alpha = 0.5f;
#endif
}
void CTriggerMultiple :: CTriggerMultiple ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CTriggerMultiple::Respawn();
CBaseEntity::CBaseEntity();
CBaseTrigger::InitBrushTrigger();
}
CLASSEXPORT( trigger_multiple, CTriggerMultiple )

View file

@ -0,0 +1,62 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// TODO: These are missing
enumflags
{
TO_MONSTERS,
TO_NOCLIENTS,
TO_PUSHABLES
};
class CTriggerOnce : CBaseTrigger
{
float m_flDelay;
void() CTriggerOnce;
virtual void() touch;
virtual void() Respawn;
};
void CTriggerOnce :: touch ( void )
{
if ( m_flDelay > 0 ) {
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
CBaseTrigger::UseTargets();
}
solid = SOLID_NOT;
#ifdef GS_DEVELOPER
alpha = 0.001f;
#endif
}
void CTriggerOnce :: Respawn ( void )
{
solid = SOLID_TRIGGER;
#ifdef GS_DEVELOPER
alpha = 0.5f;
#endif
}
void CTriggerOnce :: CTriggerOnce ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CTriggerOnce::Respawn();
CBaseEntity::CBaseEntity();
CBaseTrigger::InitBrushTrigger();
}
CLASSEXPORT( trigger_once, CTriggerOnce )

View file

@ -0,0 +1,111 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define TP_ONCE 1
#define TP_STARTOFF 2
#define TP_AAAA 4
class CTriggerPush : CBaseTrigger
{
vector m_vecMoveDir;
float m_flDelay;
float m_flSpeed;
void() CTriggerPush;
virtual void() touch;
virtual void() Respawn;
virtual void() Trigger;
virtual void() SetMovementDirection;
};
void CTriggerPush :: 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';
//m_vecMoveDir *= 1;
}
void CTriggerPush :: Trigger ( void )
{
if ( solid == SOLID_NOT ) {
solid = SOLID_TRIGGER;
} else {
solid = SOLID_NOT;
}
}
void CTriggerPush :: touch ( void )
{
switch( other.movetype )
{
case MOVETYPE_NONE:
case MOVETYPE_PUSH:
case MOVETYPE_NOCLIP:
case MOVETYPE_FOLLOW:
return;
}
if ( other.solid != SOLID_NOT && other.solid != SOLID_BSP ) {
if ( spawnflags & TP_ONCE ) {
other.velocity = other.velocity + (m_flSpeed * m_vecMoveDir);
if ( other.velocity[2] > 0 )
other.flags &= ~FL_ONGROUND;
remove( self );
} else {
/*vector vecPush = m_flSpeed * m_vecMoveDir;
if ( other.flags & FL_BASEVELOCITY ) {
vecPush = vecPush + other.basevelocity;
}
other.basevelocity = vecPush;
other.flags |= FL_BASEVELOCITY;*/
}
}
}
void CTriggerPush :: Respawn ( void )
{
if ( angles == '0 0 0' ) {
angles[1] = 360;
}
SetMovementDirection();
if ( m_flSpeed == 0 ) {
m_flSpeed = 100;
}
if ( spawnflags & TP_STARTOFF ) {
solid = SOLID_NOT;
}
}
void CTriggerPush :: CTriggerPush ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CBaseTrigger::CBaseTrigger();
CBaseTrigger::InitBrushTrigger();
CTriggerPush::Respawn();
}
CLASSEXPORT( trigger_push, CTriggerPush )

View file

@ -0,0 +1,9 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
CLASSEXPORT( trigger_relay, CTriggerOnce )

View file

@ -0,0 +1,30 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerTeleport : CBaseTrigger
{
void() CTriggerTeleport;
virtual void() touch;
};
void CTriggerTeleport :: touch ( void )
{
if ( other.health > 0 || other.solid == SOLID_SLIDEBOX ) {
entity eTarget = find( world, ::targetname, target );
setorigin( other, eTarget.origin );
}
}
void CTriggerTeleport :: CTriggerTeleport ( void )
{
CBaseTrigger::CBaseTrigger();
CBaseTrigger::InitBrushTrigger();
}
CLASSEXPORT( trigger_teleport, CTriggerTeleport )
CLASSEXPORT( info_teleport_destination, CInfoNull )

View file

@ -0,0 +1,23 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CTriggerVolume
{
void() CTriggerVolume;
};
void CTriggerVolume :: CTriggerVolume ( void )
{
solid = SOLID_NOT;
movetype = MOVETYPE_NONE;
setmodel( this, model );
model = __NULL__;
modelindex = 0;
}
CLASSEXPORT( trigger_transition, CTriggerVolume )

View file

@ -0,0 +1,49 @@
/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
class CWorld
{
void() CWorld;
virtual void() Precaches;
virtual void() SetupLight;
};
void CWorld :: Precaches ( void )
{
Material_Init();
Weapon_Init();
}
void CWorld :: SetupLight ( void )
{
// Valve BSP only
if ( serverkeyfloat( "*bspversion" ) == 30 ) {
lightstyle( 0, "m" );
lightstyle( 1, "mmnmmommommnonmmonqnmmo" );
lightstyle( 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba" );
lightstyle( 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg" );
lightstyle( 4, "mamamamamama" );
lightstyle( 5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj" );
lightstyle( 6, "nmonqnmomnmomomno" );
lightstyle( 7, "mmmaaaabcdefgmmmmaaaammmaamm" );
lightstyle( 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa" );
lightstyle( 9, "aaaaaaaazzzzzzzz" );
lightstyle( 10, "mmamammmmammamamaaamammma" );
lightstyle( 11, "abcdefghijklmnopqrrqponmlkjihgfedcba" );
}
clientstat( 16, EV_FLOAT, ::view_ofs[2] );
}
void CWorld :: CWorld ( void )
{
CWorld::Precaches();
CWorld::SetupLight();
}
//CLASSEXPORT( worldspawn, CWorld )

Binary file not shown.

Binary file not shown.

Binary file not shown.