mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-05-11 04:56:41 +03:00
Hard reset
This commit is contained in:
commit
09bed43f97
1594 changed files with 892326 additions and 0 deletions
545
code/game/game.cpp
Normal file
545
code/game/game.cpp
Normal file
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
===========================================================================
|
||||
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
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// game.cpp : General Game Info.
|
||||
|
||||
#include "game.h"
|
||||
#include "scriptmaster.h"
|
||||
#include "world.h"
|
||||
|
||||
#ifdef GAME_DLL
|
||||
#include "../game/camera.h"
|
||||
#include "../game/entity.h"
|
||||
#include "../game/player.h"
|
||||
#include "../game/dm_manager.h"
|
||||
#endif
|
||||
|
||||
Game game;
|
||||
|
||||
void G_BeginIntermission
|
||||
(
|
||||
const char *map_name,
|
||||
INTTYPE_e transtype
|
||||
)
|
||||
|
||||
{
|
||||
Entity *camera;
|
||||
Entity *node;
|
||||
Event *ev;
|
||||
gentity_t *client;
|
||||
int i;
|
||||
|
||||
if( level.intermissiontime || g_gametype->integer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
level.intermissiontime = level.time;
|
||||
level.intermissiontype = transtype;
|
||||
|
||||
G_FadeOut( 2.0f );
|
||||
G_FadeSound( 4.0f );
|
||||
|
||||
level.nextmap = map_name;
|
||||
|
||||
camera = ( Entity * )G_FindClass( NULL, "info_player_intermission" );
|
||||
if( camera )
|
||||
{
|
||||
SetCamera( camera, 0.5f );
|
||||
|
||||
ev = new Event( EV_Camera_Orbit );
|
||||
|
||||
node = ( Entity * )G_FindTarget( NULL, "endnode1" );
|
||||
if( node && node->IsSubclassOfEntity() )
|
||||
{
|
||||
ev->AddEntity( node );
|
||||
camera->ProcessEvent( ev );
|
||||
camera->ProcessEvent( EV_Camera_Cut );
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0, client = g_entities; i < game.maxclients; client++, i++ )
|
||||
{
|
||||
if( !client->inuse || !client->entity ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
client->entity->flags |= FL_IMMOBILE;
|
||||
client->entity->PostEvent( EV_Player_EnterIntermission, 3.0f );
|
||||
}
|
||||
}
|
||||
|
||||
void G_BeginIntermission2( void )
|
||||
{
|
||||
gentity_t *client;
|
||||
Entity *ent;
|
||||
int i;
|
||||
|
||||
if( level.intermissiontime ) {
|
||||
return;
|
||||
}
|
||||
|
||||
level.playerfrozen = qtrue;
|
||||
level.intermissiontime = level.time;
|
||||
|
||||
ent = ( Entity * )G_FindClass( NULL, "info_player_intermission" );
|
||||
|
||||
G_FadeSound( 4.0f );
|
||||
|
||||
if( ent )
|
||||
{
|
||||
SetCamera( ent, 0.5f );
|
||||
}
|
||||
else
|
||||
{
|
||||
G_FadeOut( 2.0f );
|
||||
}
|
||||
|
||||
for( i = 0, client = g_entities; i < game.maxclients; i++, client++ )
|
||||
{
|
||||
if( !client->inuse || !client->entity || !client->client ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ent = client->entity;
|
||||
|
||||
G_DisplayScores( ent );
|
||||
ent->flags |= FL_IMMOBILE;
|
||||
}
|
||||
}
|
||||
|
||||
void G_ExitIntermission( void )
|
||||
{
|
||||
level.exitintermission = qtrue;
|
||||
}
|
||||
|
||||
void G_CheckIntermissionExit( void )
|
||||
{
|
||||
if( !level.exitintermission && g_maxintermission->value > level.time - level.intermissiontime ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( level.nextmap != level.current_map )
|
||||
{
|
||||
G_ExitLevel();
|
||||
}
|
||||
else
|
||||
{
|
||||
G_RestartLevelWithDelay( 0.1f );
|
||||
|
||||
level.nextmap = "";
|
||||
level.intermissiontime = 0;
|
||||
level.exitintermission = qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
void ClosePlayerLogFile( void );
|
||||
|
||||
void G_ExitLevel
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
static const char *seps = " ,\n\r";
|
||||
char command[ 256 ];
|
||||
int j;
|
||||
gentity_t *ent;
|
||||
|
||||
|
||||
// Don't allow exit level if the mission was failed
|
||||
|
||||
if( level.mission_failed )
|
||||
return;
|
||||
|
||||
// close the player log file if necessary
|
||||
ClosePlayerLogFile();
|
||||
|
||||
// kill the sounds
|
||||
Com_sprintf( command, sizeof( command ), "stopsound\n" );
|
||||
gi.SendConsoleCommand( command );
|
||||
|
||||
if( g_gametype->integer )
|
||||
{
|
||||
if( strlen( sv_nextmap->string ) )
|
||||
{
|
||||
// The nextmap cvar was set (possibly by a vote - so go ahead and use it)
|
||||
level.nextmap = sv_nextmap->string;
|
||||
gi.Cvar_Set( "nextmap", "" );
|
||||
}
|
||||
else // Use the next map in the maplist
|
||||
{
|
||||
char *s, *f, *t;
|
||||
|
||||
f = NULL;
|
||||
s = strdup( sv_maplist->string );
|
||||
t = strtok( s, seps );
|
||||
while( t != NULL )
|
||||
{
|
||||
if( !Q_stricmp( t, level.mapname.c_str() ) )
|
||||
{
|
||||
// it's in the list, go to the next one
|
||||
t = strtok( NULL, seps );
|
||||
if( t == NULL ) // end of list, go to first one
|
||||
{
|
||||
if( f == NULL ) // there isn't a first one, same level
|
||||
{
|
||||
level.nextmap = level.mapname;
|
||||
}
|
||||
else
|
||||
{
|
||||
level.nextmap = f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
level.nextmap = t;
|
||||
}
|
||||
free( s );
|
||||
goto out;
|
||||
}
|
||||
|
||||
// set the first map
|
||||
if( !f )
|
||||
{
|
||||
f = t;
|
||||
}
|
||||
t = strtok( NULL, seps );
|
||||
}
|
||||
free( s );
|
||||
}
|
||||
out:
|
||||
// level.nextmap should be set now, but if it isn't use the same map
|
||||
if( level.nextmap.length() == 0 )
|
||||
{
|
||||
// Stay on the same map since no nextmap was set
|
||||
Com_sprintf( command, sizeof( command ), "restart\n" );
|
||||
gi.SendConsoleCommand( command );
|
||||
}
|
||||
else // use the level.nextmap variable
|
||||
{
|
||||
Com_sprintf( command, sizeof( command ), "gamemap \"%s\"\n", level.nextmap.c_str() );
|
||||
gi.SendConsoleCommand( command );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_sprintf( command, sizeof( command ), "gamemap \"%s\"\n", level.nextmap.c_str() );
|
||||
gi.SendConsoleCommand( command );
|
||||
}
|
||||
|
||||
// Tell all the clients that the level is done
|
||||
for( j = 0; j < game.maxclients; j++ )
|
||||
{
|
||||
ent = &g_entities[ j ];
|
||||
if( !ent->inuse || !ent->entity )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ent->entity->ProcessEvent( EV_Player_EndLevel );
|
||||
}
|
||||
|
||||
level.nextmap = "";
|
||||
|
||||
level.exitintermission = 0;
|
||||
level.intermissiontime = 0;
|
||||
|
||||
G_ClientEndServerFrames();
|
||||
}
|
||||
|
||||
void G_RestartLevelWithDelay( float delaytime )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( level.died_already ) {
|
||||
return;
|
||||
}
|
||||
|
||||
level.died_already = true;
|
||||
|
||||
// Restart the level soon
|
||||
for( i = 0; i < game.maxclients; i++ )
|
||||
{
|
||||
if( g_entities[ i ].inuse )
|
||||
{
|
||||
if( g_entities[ i ].entity )
|
||||
{
|
||||
g_entities[ i ].entity->PostEvent( EV_Player_Respawn, delaytime );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G_UpdateMatchEndTime( void )
|
||||
{
|
||||
int endtime = 0;
|
||||
|
||||
if( dmManager.GameHasRounds() && dmManager.GetRoundLimit() )
|
||||
{
|
||||
endtime = dmManager.GetMatchStartTime() * 1000.0f + ( level.svsStartTime + 60000 * dmManager.GetRoundLimit() );
|
||||
}
|
||||
else if( timelimit->integer )
|
||||
{
|
||||
endtime = level.svsStartTime + 60000 * timelimit->integer;
|
||||
}
|
||||
|
||||
if( level.svsEndTime != endtime )
|
||||
{
|
||||
level.svsEndTime = endtime;
|
||||
gi.SetConfigstring( CS_MATCHEND, va( "%i", endtime ) );
|
||||
}
|
||||
}
|
||||
|
||||
int G_GetClientNumber( gentity_t *ent )
|
||||
{
|
||||
return ent->client->ps.clientNum;
|
||||
}
|
||||
|
||||
int G_GetClientNumber( Entity *entity )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SimpleArchivedEntity *G_FindArchivedClass( SimpleArchivedEntity *ent, const char *classname )
|
||||
{
|
||||
SimpleArchivedEntity *arcent;
|
||||
int i;
|
||||
|
||||
if( ent )
|
||||
{
|
||||
i = level.m_SimpleArchivedEntities.IndexOfObject( ( SimpleArchivedEntity * )ent ) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = level.m_SimpleArchivedEntities.NumObjects();
|
||||
}
|
||||
|
||||
for( ; i > 0; i-- )
|
||||
{
|
||||
arcent = level.m_SimpleArchivedEntities.ObjectAt( i );
|
||||
|
||||
if( !Q_stricmp( arcent->getClassID(), classname ) )
|
||||
{
|
||||
return arcent;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Entity *G_FindClass( Entity *ent, const char *classname )
|
||||
{
|
||||
int entnum;
|
||||
gentity_t *from;
|
||||
|
||||
if( ent )
|
||||
{
|
||||
entnum = ent->entnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
entnum = -1;
|
||||
}
|
||||
|
||||
for( from = &g_entities[ entnum + 1 ]; from < &g_entities[ globals.num_entities ]; from++ )
|
||||
{
|
||||
if( !from->inuse )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( !Q_stricmp( from->entity->getClassID(), classname ) )
|
||||
{
|
||||
return from->entity;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Entity *G_GetEntity( int ent_num )
|
||||
{
|
||||
gentity_t * ent = &globals.gentities[ ent_num ];
|
||||
|
||||
if( ent_num < 0 || ent_num > globals.max_entities )
|
||||
{
|
||||
gi.DPrintf( "G_GetEntity: %d out of valid range.\n", ent_num );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ent->entity;
|
||||
}
|
||||
|
||||
Entity *G_GetEntityByClient( int clientNum )
|
||||
{
|
||||
gentity_t * ent = globals.gentities;
|
||||
if ( clientNum < 0 || clientNum > globals.max_entities )
|
||||
{
|
||||
gi.DPrintf( "G_GetEntity: %d out of valid range.", clientNum );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( int i = 0; i < globals.num_entities; i++, ent++ )
|
||||
{
|
||||
if ( ent->s.clientNum == clientNum )
|
||||
break;
|
||||
}
|
||||
|
||||
return ent->entity;
|
||||
}
|
||||
|
||||
int G_GetEntityIndex( int number )
|
||||
{
|
||||
gentity_t * ent = globals.gentities;
|
||||
|
||||
if( number < 0 || number > globals.max_entities ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( int i = 0; i < globals.num_entities; i++, ent++ )
|
||||
{
|
||||
if( ent->s.number == number ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int G_GetEntityIndex( gentity_t * ent )
|
||||
{
|
||||
return G_GetEntityIndex( ent->s.number );
|
||||
}
|
||||
|
||||
gentity_t * G_GetGEntity( int ent_num )
|
||||
{
|
||||
gentity_t * ent = &globals.gentities[ ent_num ];
|
||||
|
||||
if( ent_num < 0 || ent_num > globals.max_entities )
|
||||
{
|
||||
gi.DPrintf( "G_GetEntity: %d out of valid range.\n", ent_num );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
SimpleEntity *G_FindTarget( SimpleEntity *ent, const char *name )
|
||||
{
|
||||
SimpleEntity *next;
|
||||
|
||||
if( name && name[ 0 ] )
|
||||
{
|
||||
if( name[ 0 ] == '$' )
|
||||
name++;
|
||||
|
||||
next = world->GetNextEntity( name, ent );
|
||||
|
||||
if( next )
|
||||
{
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SimpleEntity *G_FindRandomSimpleTarget( const char *name )
|
||||
{
|
||||
//int nFound;
|
||||
|
||||
// FIXME: stub
|
||||
STUB();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void G_TouchTriggers( Entity *ent )
|
||||
{
|
||||
int i;
|
||||
int num;
|
||||
int touch[ MAX_GENTITIES ];
|
||||
gentity_t *hit;
|
||||
Event *ev;
|
||||
|
||||
// dead things don't activate triggers!
|
||||
if( ( ent->client || ( ent->edict->r.svFlags & SVF_BOT ) ) && ( ent->IsDead() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
num = gi.AreaEntities( ent->absmin, ent->absmax, touch, MAX_GENTITIES );
|
||||
|
||||
// be careful, it is possible to have an entity in this
|
||||
// list removed before we get to it (killtriggered)
|
||||
for( i = 0; i < num; i++ )
|
||||
{
|
||||
hit = &g_entities[ touch[ i ] ];
|
||||
if( !hit->inuse || ( hit->entity == ent ) || ( hit->solid != SOLID_TRIGGER ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
assert( hit->entity );
|
||||
|
||||
ev = new Event( EV_Touch );
|
||||
ev->AddEntity( ent );
|
||||
hit->entity->ProcessEvent( ev );
|
||||
}
|
||||
}
|
||||
|
||||
trace_t G_Trace(
|
||||
const vec3_t start,
|
||||
const vec3_t bbox_mins,
|
||||
const vec3_t bbox_maxs,
|
||||
const vec3_t end,
|
||||
Entity *entity,
|
||||
int mask,
|
||||
qboolean cliptoentities,
|
||||
const char *description
|
||||
)
|
||||
{
|
||||
trace_t results;
|
||||
|
||||
gi.Trace( &results, start, bbox_mins, bbox_maxs, end, entity->entnum, 0, 0, false );
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
Game::Game()
|
||||
{
|
||||
clients = NULL;
|
||||
maxclients = 0;
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Game::Archive( Archiver& arc )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CLASS_DECLARATION( Listener, Game, NULL )
|
||||
{
|
||||
{ NULL, NULL }
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue