mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
535 lines
12 KiB
C++
535 lines
12 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// spawners.cpp: Various spawning entities
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED func_spawn(0 0.25 0.5) (-8 -8 -8) (8 8 8)
|
|
"modelname" The name of the TIKI file you wish to spawn. (Required)
|
|
"spawntargetname" This will be the targetname of the spawned model. (default is null)
|
|
"spawntarget" This will be the target of the spawned model. (default is null)
|
|
"pickup_thread" passed on to the spawned model
|
|
"key" The item needed to activate this. (default nothing)
|
|
"attackmode" Attacking mode of the spawned actor (default 0)
|
|
******************************************************************************/
|
|
|
|
#include "spawners.h"
|
|
#include "game.h"
|
|
#include "g_phys.h"
|
|
#include "g_spawn.h"
|
|
|
|
Event EV_Spawn_ModelName
|
|
(
|
|
"modelname",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"model_name",
|
|
"Sets the model name for this spawn entity.",
|
|
EV_NORMAL
|
|
);
|
|
Event EV_Spawn_SpawnTargetName
|
|
(
|
|
"spawntargetname",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"spawntargetname",
|
|
"Sets spawn target name for this spawn entity.",
|
|
EV_NORMAL
|
|
);
|
|
Event EV_Spawn_SpawnTarget
|
|
(
|
|
"spawntarget",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"spawntarget",
|
|
"Sets spawn target for this spawn entity.",
|
|
EV_NORMAL
|
|
);
|
|
Event EV_Spawn_AttackMode
|
|
(
|
|
"attackmode",
|
|
EV_DEFAULT,
|
|
"i",
|
|
"attackmode",
|
|
"Sets the attackmode for this spawn entity.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
Event EV_Spawn_PickupThread
|
|
(
|
|
"pickup_thread",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"threadName",
|
|
"Sets the pickup thread for the spawned entity.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
Event EV_Spawn_AddSpawnItem
|
|
(
|
|
"spawnitem",
|
|
EV_DEFAULT,
|
|
"s",
|
|
"spawn_item_name",
|
|
"Adds this named item to what will be spawned when this spawned entity is killed, if it is an actor.",
|
|
EV_NORMAL
|
|
);
|
|
Event EV_Spawn_SetSpawnChance
|
|
(
|
|
"spawnchance",
|
|
EV_DEFAULT,
|
|
"f",
|
|
"spawn_chance",
|
|
"Sets the chance that this spawned entity will spawn something when killed, if it is an actor.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
|
|
CLASS_DECLARATION( ScriptSlave, Spawn, "func_spawn" )
|
|
{
|
|
{ &EV_Activate, &Spawn::DoSpawn },
|
|
{ &EV_Spawn_ModelName, &Spawn::ModelName },
|
|
{ &EV_Spawn_SpawnTargetName, &Spawn::SpawnTargetName },
|
|
{ &EV_Spawn_AttackMode, &Spawn::AttackMode },
|
|
{ &EV_Spawn_SpawnTarget, &Spawn::SpawnTarget },
|
|
{ &EV_Spawn_PickupThread, &Spawn::SetPickupThread },
|
|
{ &EV_SetAngle, &Spawn::SetAngleEvent },
|
|
{ &EV_Spawn_AddSpawnItem, &Spawn::SetSpawnItem },
|
|
{ &EV_Spawn_SetSpawnChance, &Spawn::SetSpawnChance },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void Spawn::SetAngleEvent
|
|
(
|
|
Event *ev
|
|
)
|
|
{
|
|
SimpleEntity::SetAngleEvent( ev );
|
|
}
|
|
|
|
void Spawn::SetPickupThread
|
|
(
|
|
Event *ev
|
|
)
|
|
{
|
|
pickup_thread = ev->GetString( 1 );
|
|
}
|
|
|
|
void Spawn::ModelName
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
modelname = ev->GetString( 1 );
|
|
CacheResource( modelname );
|
|
}
|
|
|
|
void Spawn::SpawnTargetName
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
spawntargetname = ev->GetString( 1 );
|
|
}
|
|
|
|
void Spawn::SpawnTarget
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
spawntarget = ev->GetString( 1 );
|
|
}
|
|
|
|
void Spawn::AttackMode
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
attackmode = ev->GetInteger( 1 );
|
|
}
|
|
|
|
void Spawn::SetSpawnItem
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
spawnitem = ev->GetString( 1 );
|
|
}
|
|
|
|
void Spawn::SetSpawnChance
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
spawnchance = ev->GetFloat( 1 );
|
|
}
|
|
|
|
Spawn::Spawn()
|
|
{
|
|
setSolidType( SOLID_NOT );
|
|
setMoveType( MOVETYPE_NONE );
|
|
hideModel();
|
|
|
|
spawnchance = 0;
|
|
attackmode = 0;
|
|
}
|
|
|
|
void Spawn::SetArgs
|
|
(
|
|
SpawnArgs &args
|
|
)
|
|
{
|
|
args.setArg( "origin", va( "%f %f %f", origin[ 0 ], origin[ 1 ], origin[ 2 ] ) );
|
|
args.setArg( "angle", va( "%f", angles[ 1 ] ) );
|
|
args.setArg( "angles", va( "%f %f %f", angles[ 0 ], angles[ 1 ], angles[ 2 ] ) );
|
|
args.setArg( "model", modelname.c_str() );
|
|
args.setArg( "attackmode", va( "%i",attackmode ) );
|
|
args.setArg( "scale", va( "%f",edict->s.scale ) );
|
|
if ( spawntargetname.length() )
|
|
{
|
|
args.setArg( "targetname", spawntargetname.c_str() );
|
|
}
|
|
if ( spawntarget.length() )
|
|
{
|
|
args.setArg( "target", spawntarget.c_str() );
|
|
}
|
|
if ( pickup_thread.length() )
|
|
{
|
|
args.setArg( "pickup_thread", pickup_thread.c_str() );
|
|
}
|
|
if ( spawnitem.length() )
|
|
{
|
|
args.setArg( "spawnitem", spawnitem.c_str() );
|
|
args.setArg( "spawnchance", va( "%f", spawnchance ) );
|
|
}
|
|
}
|
|
|
|
void Spawn::DoSpawn
|
|
(
|
|
Event *ev
|
|
)
|
|
{
|
|
Entity *spawn;
|
|
SpawnArgs args;
|
|
|
|
if ( !modelname.length() )
|
|
{
|
|
warning("Spawn", "modelname not set" );
|
|
}
|
|
|
|
SetArgs( args );
|
|
|
|
spawn = ( Entity * )args.Spawn();
|
|
|
|
if ( spawn )
|
|
{
|
|
// make sure spawned entity starts falling if necessary
|
|
spawn->velocity = "0 0 -1";
|
|
|
|
Event *e = new Event( EV_SetAnim );
|
|
e->AddString( "idle" );
|
|
spawn->PostEvent( e, EV_SPAWNARG );
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED func_randomspawn(0 0.25 0.5) (-8 -8 -8) (8 8 8) START_OFF
|
|
Randomly spawns an entity. The time between spawns is determined by min_time and max_time
|
|
The entity can be turned off and on by triggering it
|
|
"modelname" The name of the TIKI file you wish to spawn. (Required)
|
|
"key" The item needed to activate this. (default nothing)
|
|
"min_time" The minimum time between spawns (default 0.2 seconds)
|
|
"max_time" The maximum time between spawns (default 1 seconds)
|
|
START_OFF - spawn is off by default
|
|
******************************************************************************/
|
|
|
|
Event EV_RandomSpawn_MinTime
|
|
(
|
|
"min_time",
|
|
EV_DEFAULT,
|
|
"f",
|
|
"minTime",
|
|
"Minimum time between random spawns.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
Event EV_RandomSpawn_MaxTime
|
|
(
|
|
"max_time",
|
|
EV_DEFAULT,
|
|
"f",
|
|
"maxTime",
|
|
"Maximum time between random spawns.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
Event EV_RandomSpawn_Think
|
|
(
|
|
"_randomspawn_think",
|
|
EV_DEFAULT,
|
|
NULL,
|
|
NULL,
|
|
"The function that actually spawns things in.",
|
|
EV_NORMAL
|
|
);
|
|
|
|
CLASS_DECLARATION( Spawn, RandomSpawn, "func_randomspawn" )
|
|
{
|
|
{ &EV_Activate, &RandomSpawn::ToggleSpawn },
|
|
{ &EV_RandomSpawn_MinTime, &RandomSpawn::MinTime },
|
|
{ &EV_RandomSpawn_MaxTime, &RandomSpawn::MaxTime },
|
|
{ &EV_RandomSpawn_Think, &RandomSpawn::Think },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
RandomSpawn::RandomSpawn()
|
|
{
|
|
min_time = 0.2f;
|
|
max_time = 1.0f;
|
|
if ( !LoadingSavegame && !( spawnflags & 1 ) )
|
|
{
|
|
PostEvent( EV_RandomSpawn_Think, min_time + ( G_Random( max_time - min_time ) ) );
|
|
}
|
|
}
|
|
|
|
void RandomSpawn::MinTime
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
min_time = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void RandomSpawn::MaxTime
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
max_time = ev->GetFloat( 1 );
|
|
}
|
|
|
|
void RandomSpawn::ToggleSpawn
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
if ( EventPending( EV_RandomSpawn_Think ) )
|
|
{
|
|
// if currently on, turn it off
|
|
CancelEventsOfType( EV_RandomSpawn_Think );
|
|
}
|
|
else
|
|
{
|
|
Think( NULL );
|
|
}
|
|
}
|
|
|
|
void RandomSpawn::Think( Event *ev )
|
|
{
|
|
CancelEventsOfType( EV_RandomSpawn_Think );
|
|
|
|
//
|
|
// spawn our entity
|
|
//
|
|
DoSpawn( NULL );
|
|
|
|
//
|
|
// post the next time
|
|
//
|
|
PostEvent( EV_RandomSpawn_Think, min_time + ( G_Random( max_time - min_time ) ) );
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED func_respawn(0 0.25 0.5) (-8 -8 -8) (8 8 8)
|
|
When the thing that is spawned is killed, this func_respawn will get
|
|
triggered.
|
|
"modelname" The name of the TIKI file you wish to spawn. (Required)
|
|
"key" The item needed to activate this. (default nothing)
|
|
******************************************************************************/
|
|
|
|
CLASS_DECLARATION( Spawn, ReSpawn, "func_respawn" )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void ReSpawn::DoSpawn( Event *ev )
|
|
{
|
|
Entity *spawn;
|
|
SpawnArgs args;
|
|
|
|
SetArgs( args );
|
|
|
|
// This will trigger the func_respawn when the thing dies
|
|
args.setArg( "targetname", TargetName() );
|
|
args.setArg( "target", TargetName() );
|
|
|
|
spawn = ( Entity * )args.Spawn();
|
|
if ( spawn )
|
|
{
|
|
// make sure spawned entity starts falling if necessary
|
|
spawn->velocity = "0 0 -1";
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED func_spawnoutofsight(0 0.25 0.5) (-8 -8 -8) (8 8 8)
|
|
Will only spawn something out of sight of its targets.
|
|
"modelname" The name of the TIKI file you wish to spawn. (Required)
|
|
"spawntargetname" This will be the targetname of the spawned model. (default is null)
|
|
"spawntarget" This will be the target of the spawned model. (default is null)
|
|
"key" The item needed to activate this. (default nothing)
|
|
******************************************************************************/
|
|
|
|
CLASS_DECLARATION( Spawn, SpawnOutOfSight, "func_spawnoutofsight" )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void SpawnOutOfSight::DoSpawn
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
int i;
|
|
Entity *ent;
|
|
gentity_t *ed;
|
|
trace_t trace;
|
|
qboolean seen = false;
|
|
|
|
// Check to see if I can see any players before spawning
|
|
for( i = 0; i < game.maxclients; i++ )
|
|
{
|
|
ed = &g_entities[ i ];
|
|
if ( !ed->inuse || !ed->entity )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ent = ed->entity;
|
|
if( ( ent->health < 0 ) || ( ent->flags & FL_NOTARGET ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
trace = G_Trace( origin, vec_zero, vec_zero, ent->centroid, this, MASK_OPAQUE, false, "SpawnOutOfSight::DoSpawn" );
|
|
if ( trace.fraction == 1.0 )
|
|
{
|
|
seen = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( seen )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Spawn::DoSpawn( ev );
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/*QUAKED func_spawnchain(0 0.25 0.5) (-8 -8 -8) (8 8 8)
|
|
Tries to spawn something out of the sight of players. If it fails, it will
|
|
trigger its targets.
|
|
"modelname" The name of the TIKI file you wish to spawn. (Required)
|
|
"spawntargetname" This will be the targetname of the spawned model. (default is null)
|
|
"spawntarget" This will be the target of the spawned model. (default is null)
|
|
"key" The item needed to activate this. (default nothing)
|
|
******************************************************************************/
|
|
|
|
CLASS_DECLARATION( Spawn, SpawnChain, "func_spawnchain" )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void SpawnChain::DoSpawn
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
int i;
|
|
Entity *ent;
|
|
gentity_t *ed;
|
|
trace_t trace;
|
|
qboolean seen = false;
|
|
const char *name;
|
|
Event *event;
|
|
|
|
// Check to see if this can see any players before spawning
|
|
for( i = 0; i < game.maxclients; i++ )
|
|
{
|
|
ed = &g_entities[ i ];
|
|
if ( !ed->inuse || !ed->entity )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ent = ed->entity;
|
|
if( ( ent->health < 0 ) || ( ent->flags & FL_NOTARGET ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
trace = G_Trace( origin, vec_zero, vec_zero, ent->centroid, this, MASK_OPAQUE, false, "SpawnChain::DoSpawn" );
|
|
if ( trace.fraction == 1.0 )
|
|
{
|
|
seen = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Couldn't spawn anything, so activate targets
|
|
if ( seen )
|
|
{
|
|
name = Target();
|
|
if ( name && strcmp( name, "" ) )
|
|
{
|
|
ent = NULL;
|
|
do
|
|
{
|
|
ent = ( Entity * )G_FindTarget( ent, name );
|
|
if ( !ent )
|
|
{
|
|
break;
|
|
}
|
|
event = new Event( EV_Activate );
|
|
event->AddEntity( world );
|
|
ent->PostEvent( event, 0 );
|
|
} while ( 1 );
|
|
}
|
|
return;
|
|
}
|
|
|
|
Spawn::DoSpawn( ev );
|
|
}
|