mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
3650 lines
116 KiB
C++
3650 lines
116 KiB
C++
|
|
||
|
/*****************************************************************************
|
||
|
** **
|
||
|
** Neversoft Entertainment. **
|
||
|
** **
|
||
|
** Copyright (C) 1999 - All Rights Reserved **
|
||
|
** **
|
||
|
******************************************************************************
|
||
|
** **
|
||
|
** Project: PS2 **
|
||
|
** **
|
||
|
** Module: Skate Module (SKATE) **
|
||
|
** **
|
||
|
** File name: modules/skatenet.cpp **
|
||
|
** **
|
||
|
** Created by: 02/08/2001 - spg **
|
||
|
** **
|
||
|
** Description: Skate Module's Network Handlers **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Includes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
//#include <string.h>
|
||
|
|
||
|
#include <core/defines.h>
|
||
|
#include <core/singleton.h>
|
||
|
|
||
|
#include <core/task.h>
|
||
|
#include <core/math.h>
|
||
|
|
||
|
#include <sys/sys.h>
|
||
|
#include <sys/mem/memman.h>
|
||
|
#include <sys/timer.h>
|
||
|
|
||
|
#include <gfx/gfxman.h>
|
||
|
#include <gfx/animcontroller.h>
|
||
|
#include <gfx/facetexture.h>
|
||
|
#include <gfx/skeleton.h>
|
||
|
#include <gfx/nxmodel.h>
|
||
|
|
||
|
//#include <gel/inpman.h>
|
||
|
#include <gel/objman.h>
|
||
|
#include <gel/object.h>
|
||
|
#include <gel/net/net.h>
|
||
|
#include <gel/net/server/netserv.h>
|
||
|
#include <gel/net/client/netclnt.h>
|
||
|
#include <gel/mainloop.h>
|
||
|
#include <gel/components/animationcomponent.h>
|
||
|
#include <gel/components/modelcomponent.h>
|
||
|
#include <gel/environment/terrain.h>
|
||
|
|
||
|
#include <modules/skate/skate.h>
|
||
|
#include <modules/skate/goalmanager.h>
|
||
|
#include <modules/skate/gamemode.h>
|
||
|
#include <modules/frontend/frontend.h>
|
||
|
|
||
|
#include <objects/skater.h>
|
||
|
#include <objects/skaterprofile.h>
|
||
|
#include <sk/objects/skatercareer.h>
|
||
|
|
||
|
#include <sk/gamenet/gamenet.h>
|
||
|
#include <sk/components/skaterstatehistorycomponent.h>
|
||
|
#include <sk/components/skaterlocalnetlogiccomponent.h>
|
||
|
|
||
|
#include <gel/scripting/script.h>
|
||
|
#include <gel/scripting/array.h>
|
||
|
#include <gel/scripting/symboltable.h>
|
||
|
#include <gel/scripting/checksum.h>
|
||
|
#include <scripting/cfuncs.h>
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** DBG Information **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
namespace Mdl
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Externals **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Defines **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#define vFORCE_UPDATE_INTERVAL 60
|
||
|
#define vOBJ_UPDATE_THRESHOLD FEET( 150 )
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Types **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
class ObjUpdateInfo
|
||
|
{
|
||
|
public:
|
||
|
Net::BitStream m_BitStream;
|
||
|
int m_Handle;
|
||
|
GameNet::PlayerInfo* m_Player;
|
||
|
};
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Classes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Prototypes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Create all network-related tasks and handlers */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::net_setup( void )
|
||
|
{
|
||
|
// Server net tasks
|
||
|
m_object_update_task = new Tsk::Task< Skate > ( Skate::s_object_update_code, *this,
|
||
|
Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_OBJECT_UPDATE );
|
||
|
m_score_update_task = new Tsk::Task< Skate > ( Skate::s_score_update_code, *this,
|
||
|
Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_SCORE_UPDATE );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* delete all network-related tasks and handlers */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::net_shutdown( void )
|
||
|
{
|
||
|
// Server net tasks
|
||
|
delete m_object_update_task;
|
||
|
delete m_score_update_task;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Determines whether we should send "send_player" an update */
|
||
|
/* concerning "object" */
|
||
|
/******************************************************************/
|
||
|
|
||
|
bool Skate::should_send_update( GameNet::PlayerInfo* send_player, Obj::CObject* object )
|
||
|
{
|
||
|
Obj::SPosEvent* latest_state;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* skater_player;
|
||
|
Obj::CSkater* skater_obj;
|
||
|
int id, index;
|
||
|
|
||
|
// Dont send a client updates on his own skater. He is up to date.
|
||
|
skater_player = gamenet_man->GetPlayerByObjectID( object->GetID() );
|
||
|
if( ( skater_player == NULL ) ||
|
||
|
( skater_player == send_player ))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
skater_obj = skater_player->m_Skater;
|
||
|
// Check if we have something to report
|
||
|
if( skater_obj->GetStateHistory()->GetNumPosUpdates() == 0 )
|
||
|
{
|
||
|
//Dbg_Printf( "Not enough pos updates\n" );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
id = skater_obj->GetID();
|
||
|
index = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
latest_state = &skater_obj->GetStateHistory()->GetPosHistory()[index];
|
||
|
|
||
|
// Only send an update if there's something new to tell
|
||
|
if( latest_state->LoTime == send_player->m_LastSentProps.m_LastSkaterUpdateTime[id] )
|
||
|
{
|
||
|
//Dbg_Printf( "Nothing new to tell\n" );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Decide which fields need to be updated for this object */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
static int s_get_update_flags( GameNet::PlayerInfo* player,
|
||
|
Obj::SPosEvent* latest_state,
|
||
|
int skater_id )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
int i, update_flags;
|
||
|
short pos[3];
|
||
|
short rot[3];
|
||
|
Flags< int > skater_flags;
|
||
|
Flags< int > end_run_flags;
|
||
|
Mth::Vector eulers;
|
||
|
char state, doing_trick, terrain, walking, driving;
|
||
|
bool forced_send;
|
||
|
unsigned char id;
|
||
|
sint16 rail_node;
|
||
|
|
||
|
update_flags = 0;
|
||
|
|
||
|
// Force an object update every N frames
|
||
|
forced_send = !( gamenet_man->GetServer()->m_FrameCounter % vFORCE_UPDATE_INTERVAL );
|
||
|
id = skater_id;
|
||
|
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
eulers[i] = latest_state->Eulers[i];
|
||
|
}
|
||
|
|
||
|
// Write out the object's position as three shorts (fixed-point)
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
if( i == Y )
|
||
|
{
|
||
|
pos[i] = (short) ( latest_state->Position[i] * 4.0f );
|
||
|
//pos[i] = latest_state->Position[i];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pos[i] = (short) ( latest_state->Position[i] * 2.0f );
|
||
|
//pos[i] = latest_state->Position[i];
|
||
|
}
|
||
|
if(( pos[i] != player->m_LastSentProps.m_LastSkaterPosUpdate[id][i] ) || forced_send )
|
||
|
{
|
||
|
if( i == X )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_POS_X;
|
||
|
}
|
||
|
else if( i == Y )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_POS_Y;
|
||
|
}
|
||
|
else if( i == Z )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_POS_Z;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Write out the object's orientation as three short euler angles (fixed-point)
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
rot[i] = (short) ( eulers[i] * 4096.0f );
|
||
|
if(( rot[i] != player->m_LastSentProps.m_LastSkaterRotUpdate[id][i] ) || forced_send )
|
||
|
{
|
||
|
if( i == X )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_ROT_X;
|
||
|
}
|
||
|
else if( i == Y )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_ROT_Y;
|
||
|
}
|
||
|
else if( i == Z )
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_ROT_Z;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
state = (char) latest_state->State;
|
||
|
doing_trick = (char) latest_state->DoingTrick;
|
||
|
terrain = (char) latest_state->Terrain;
|
||
|
walking = (char) latest_state->Walking;
|
||
|
driving = (char) latest_state->Driving;
|
||
|
|
||
|
if(( state != player->m_LastSentProps.m_LastSkaterStateUpdate[id] ) ||
|
||
|
( doing_trick != player->m_LastSentProps.m_LastDoingTrickUpdate[id] ) ||
|
||
|
( terrain != player->m_LastSentProps.m_LastSkaterTerrain[id] ) ||
|
||
|
( walking != player->m_LastSentProps.m_LastSkaterWalking[id] ) ||
|
||
|
( driving != player->m_LastSentProps.m_LastSkaterDriving[id] ) ||
|
||
|
( forced_send == true ))
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_STATE;
|
||
|
}
|
||
|
|
||
|
skater_flags = latest_state->SkaterFlags;
|
||
|
end_run_flags = latest_state->EndRunFlags;
|
||
|
|
||
|
if(( skater_flags != player->m_LastSentProps.m_LastSkaterFlagsUpdate[id] ) ||
|
||
|
( end_run_flags != player->m_LastSentProps.m_LastEndRunFlagsUpdate[id] ) ||
|
||
|
( forced_send == true ))
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_FLAGS;
|
||
|
}
|
||
|
|
||
|
rail_node = latest_state->RailNode;
|
||
|
if(( rail_node != player->m_LastSentProps.m_LastRailNodeUpdate[id] ) ||
|
||
|
( forced_send == true ))
|
||
|
{
|
||
|
update_flags |= GameNet::mUPDATE_FIELD_RAIL_NODE;
|
||
|
}
|
||
|
|
||
|
return update_flags;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Place positional/state update data in the outbound stream */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::s_object_update( Obj::CObject* object, void* data )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* player, *skater_player;
|
||
|
ObjUpdateInfo* update_info;
|
||
|
Obj::CSkater* skater_obj;
|
||
|
Mth::Vector eulers;
|
||
|
short pos[3];
|
||
|
short rot[3];
|
||
|
unsigned char id;
|
||
|
char state, doing_trick, terrain, walking, driving;
|
||
|
Flags< int > skater_flags;
|
||
|
Flags< int > end_run_flags;
|
||
|
int update_flags;
|
||
|
Obj::SPosEvent* latest_state;
|
||
|
int i, index;
|
||
|
unsigned short time;
|
||
|
|
||
|
Dbg_Assert( data );
|
||
|
|
||
|
update_info = (ObjUpdateInfo *) data;
|
||
|
|
||
|
skater_player = gamenet_man->GetPlayerByObjectID( object->GetID() );
|
||
|
skater_obj = skater_player->m_Skater;
|
||
|
id = (char) skater_obj->GetID();
|
||
|
player = update_info->m_Player;
|
||
|
index = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
latest_state = &skater_obj->GetStateHistory()->GetPosHistory()[index];
|
||
|
player->m_LastSentProps.m_LastSkaterUpdateTime[id] = latest_state->GetTime();
|
||
|
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
eulers[i] = latest_state->Eulers[i];
|
||
|
}
|
||
|
|
||
|
time = latest_state->LoTime;
|
||
|
update_info->m_BitStream.WriteValue( time, sizeof( uint16 ) * 8 );
|
||
|
|
||
|
update_flags = s_get_update_flags( player, latest_state, id );
|
||
|
update_info->m_BitStream.WriteValue( update_flags, 9 );
|
||
|
|
||
|
//Dbg_Printf( "*** Sending Pos[%.2f %.2f %.2f]\n", latest_state->Position[X], latest_state->Position[Y], latest_state->Position[Z] );
|
||
|
// Write out the object's position as three shorts (fixed-point)
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
if( i == Y )
|
||
|
{
|
||
|
pos[i] = (short) ( latest_state->Position[i] * 4.0f );
|
||
|
//pos[i] = latest_state->Position[i];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pos[i] = (short) ( latest_state->Position[i] * 2.0f );
|
||
|
//pos[i] = latest_state->Position[i];
|
||
|
}
|
||
|
|
||
|
if( i == X )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_X )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );
|
||
|
//update_info->m_BitStream.WriteFloatValue( pos[i] );
|
||
|
}
|
||
|
}
|
||
|
else if( i == Y )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Y )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );
|
||
|
//update_info->m_BitStream.WriteFloatValue( pos[i] );
|
||
|
}
|
||
|
}
|
||
|
else if( i == Z )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Z )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( pos[i], sizeof( short ) * 8 );
|
||
|
//update_info->m_BitStream.WriteFloatValue( pos[i] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player->m_LastSentProps.m_LastSkaterPosUpdate[id][i] = pos[i];
|
||
|
}
|
||
|
|
||
|
// Write out the object's orientation as three short euler angles (fixed-point)
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
rot[i] = (short) ( eulers[i] * 4096.0f );
|
||
|
if( i == X )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_X )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );
|
||
|
}
|
||
|
}
|
||
|
else if( i == Y )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );
|
||
|
}
|
||
|
}
|
||
|
else if( i == Z )
|
||
|
{
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )
|
||
|
{
|
||
|
update_info->m_BitStream.WriteValue( rot[i], sizeof( short ) * 8 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player->m_LastSentProps.m_LastSkaterRotUpdate[id][i] = rot[i];
|
||
|
}
|
||
|
|
||
|
state = (char) latest_state->State;
|
||
|
doing_trick = (char) latest_state->DoingTrick;
|
||
|
terrain = (char) latest_state->Terrain;
|
||
|
walking = (char) latest_state->Walking;
|
||
|
driving = (char) latest_state->Driving;
|
||
|
|
||
|
// Write out the skaters' state
|
||
|
// Write out the skater's "doing trick" flag
|
||
|
// Write out the skater's terrain type
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_STATE )
|
||
|
{
|
||
|
char mask;
|
||
|
|
||
|
mask = state;
|
||
|
if( doing_trick )
|
||
|
{
|
||
|
mask |= GameNet::mDOING_TRICK_MASK;
|
||
|
}
|
||
|
|
||
|
update_info->m_BitStream.WriteValue( mask, 4 );
|
||
|
update_info->m_BitStream.WriteValue( terrain, 6 );
|
||
|
update_info->m_BitStream.WriteValue( walking, 1 );
|
||
|
update_info->m_BitStream.WriteValue( driving, 1 );
|
||
|
|
||
|
player->m_LastSentProps.m_LastSkaterStateUpdate[id] = state;
|
||
|
player->m_LastSentProps.m_LastDoingTrickUpdate[id] = doing_trick;
|
||
|
player->m_LastSentProps.m_LastSkaterTerrain[id] = terrain;
|
||
|
player->m_LastSentProps.m_LastSkaterWalking[id] = walking;
|
||
|
player->m_LastSentProps.m_LastSkaterDriving[id] = driving;
|
||
|
}
|
||
|
|
||
|
// Write out the skaters' flags
|
||
|
skater_flags = latest_state->SkaterFlags;
|
||
|
end_run_flags = latest_state->EndRunFlags;
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_FLAGS )
|
||
|
{
|
||
|
player->m_LastSentProps.m_LastSkaterFlagsUpdate[id] = skater_flags;
|
||
|
player->m_LastSentProps.m_LastEndRunFlagsUpdate[id] = end_run_flags;
|
||
|
update_info->m_BitStream.WriteValue( skater_flags, 5 );
|
||
|
update_info->m_BitStream.WriteValue( end_run_flags, 3 );
|
||
|
}
|
||
|
|
||
|
// Write out the skaters' rail node
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )
|
||
|
{
|
||
|
player->m_LastSentProps.m_LastRailNodeUpdate[id] = latest_state->RailNode;
|
||
|
update_info->m_BitStream.WriteValue( latest_state->RailNode, sizeof( sint16 ) * 8 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Update Clients with objects' positional/rotational/anim data */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::s_object_update_code ( const Tsk::Task< Skate >& task )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* player;
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
Net::Server* server;
|
||
|
|
||
|
Dbg_AssertType ( &task, Tsk::Task< Skate > );
|
||
|
Skate& mdl = task.GetData();
|
||
|
|
||
|
server = gamenet_man->GetServer();
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player =
|
||
|
gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
Net::MsgMax update_msg;
|
||
|
unsigned int length;
|
||
|
ObjUpdateInfo update_info;
|
||
|
GameNet::PlayerInfo* update_player;
|
||
|
int i, start_id, obj_id, num_updates;
|
||
|
|
||
|
// Don't send updates to the local client. His stuff is already up-to-date
|
||
|
if( player->m_Conn->IsRemote())
|
||
|
{
|
||
|
int obj_id_mask;
|
||
|
|
||
|
update_info.m_BitStream.SetOutputData( update_msg.m_Data, 4096 ); // skip Obj ID Mask
|
||
|
update_info.m_Handle = player->m_Conn->GetHandle();
|
||
|
update_info.m_Player = player;
|
||
|
|
||
|
obj_id_mask = 0;
|
||
|
|
||
|
// First decide which objects' updates we will send, then append them to the stream
|
||
|
// in increasing id order
|
||
|
num_updates = 0;
|
||
|
start_id = ( player->GetLastObjectUpdateID() + 1 ) % vMAX_SKATERS;
|
||
|
for( i = 0; i < vMAX_SKATERS; i++ )
|
||
|
{
|
||
|
obj_id = ( start_id + i ) % vMAX_SKATERS;
|
||
|
update_player = gamenet_man->GetPlayerByObjectID( obj_id );
|
||
|
if( update_player )
|
||
|
{
|
||
|
if( mdl.should_send_update( player, update_player->m_Skater ))
|
||
|
{
|
||
|
obj_id_mask |= ( 1 << obj_id );
|
||
|
if( ++num_updates >= player->GetMaxObjectUpdates())
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( num_updates == 0 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
update_info.m_BitStream.WriteValue( obj_id_mask, sizeof( char ) * 8 );
|
||
|
for( i = 0; i < vMAX_SKATERS; i++ )
|
||
|
{
|
||
|
if( obj_id_mask & ( 1 << i ))
|
||
|
{
|
||
|
update_player = gamenet_man->GetPlayerByObjectID( i );
|
||
|
|
||
|
s_object_update( update_player->m_Skater, &update_info );
|
||
|
player->SetLastObjectUpdateID( i );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
update_info.m_BitStream.Flush();
|
||
|
length = update_info.m_BitStream.GetByteLength();
|
||
|
|
||
|
if( length > 0 )
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
msg_desc.m_Data = &update_msg;
|
||
|
msg_desc.m_Length = length;
|
||
|
msg_desc.m_Id = GameNet::MSG_ID_OBJ_UPDATE_STREAM;
|
||
|
server->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Update Clients with other players' scores */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::SendScoreUpdates( bool final )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* player, *score_player;
|
||
|
Lst::Search< GameNet::PlayerInfo > sh, score_sh;
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player =
|
||
|
gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
GameNet::MsgScoreUpdate score_msg;
|
||
|
char num_scores;
|
||
|
int length;
|
||
|
char* data;
|
||
|
|
||
|
score_msg.m_Final = (char) final;
|
||
|
if( final )
|
||
|
{
|
||
|
score_msg.m_TimeLeft = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
score_msg.m_TimeLeft = Tmr::InSeconds( GetGameMode()->GetTimeLeft());
|
||
|
}
|
||
|
num_scores = 0;
|
||
|
data = score_msg.m_ScoreData;
|
||
|
for( score_player = gamenet_man->FirstPlayerInfo( score_sh ); score_player; score_player =
|
||
|
gamenet_man->NextPlayerInfo( score_sh ))
|
||
|
{
|
||
|
bool send_all_scores;
|
||
|
|
||
|
send_all_scores = final ||
|
||
|
( GetGameMode()->IsTrue( "should_modulate_color" )) ||
|
||
|
( GetGameMode()->ShouldTrackTrickScore() == false );
|
||
|
if( ( score_player != player ) || ( send_all_scores ) )
|
||
|
{
|
||
|
char id;
|
||
|
int score;
|
||
|
bool in_goal_attack;
|
||
|
|
||
|
id = (char) score_player->m_Skater->GetID();
|
||
|
in_goal_attack = GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netgoalattack" );
|
||
|
|
||
|
if( in_goal_attack )
|
||
|
{
|
||
|
Game::CGoalManager* pGoalManager;
|
||
|
|
||
|
pGoalManager = Game::GetGoalManager();
|
||
|
score = pGoalManager->NumGoalsBeatenBy( score_player->m_Skater->GetID());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
score = gamenet_man->GetPlayerScore( score_player->m_Skater->GetID());
|
||
|
}
|
||
|
|
||
|
*data = id;
|
||
|
data++;
|
||
|
memcpy( data, &score, sizeof( int ));
|
||
|
data += sizeof( int );
|
||
|
|
||
|
num_scores++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( num_scores > 0 )
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
score_msg.m_Cheats = GetCheatChecksum();
|
||
|
score_msg.m_NumScores = num_scores;
|
||
|
length = sizeof( int ) + // m_TimeLeft
|
||
|
sizeof( int ) + // m_Cheats
|
||
|
sizeof( char ) + // m_Final
|
||
|
sizeof( char ) + // m_NumScores
|
||
|
(( sizeof( char ) + sizeof( int )) * num_scores );
|
||
|
|
||
|
msg_desc.m_Data = &score_msg;
|
||
|
msg_desc.m_Length = length;
|
||
|
msg_desc.m_Id = GameNet::MSG_ID_SCORE_UPDATE;
|
||
|
// If it's the final tally or if it's reporting cheats, it HAS to get there
|
||
|
if( final || ( score_msg.m_Cheats != 0 ))
|
||
|
{
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
}
|
||
|
|
||
|
gamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
|
||
|
if( !player->IsLocalPlayer() && player->IsFullyIn())
|
||
|
{
|
||
|
GameNet::MsgCheatChecksum cheat_msg;
|
||
|
|
||
|
cheat_msg.m_ServerChecksum = GetCheatChecksum();
|
||
|
cheat_msg.m_ServerChecksum ^= 0xDEADFACE;
|
||
|
msg_desc.m_Id = GameNet::MSG_ID_CHEAT_CHECKSUM_REQUEST;
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
msg_desc.m_Data = &cheat_msg;
|
||
|
msg_desc.m_Length = sizeof( GameNet::MsgCheatChecksum );
|
||
|
|
||
|
gamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gamenet_man->SetLastScoreUpdateTime( gamenet_man->GetServer()->m_Timestamp );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Periodic task to update Clients with other players' scores */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::s_score_update_code ( const Tsk::Task< Skate >& task )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Skate& mdl = task.GetData();
|
||
|
|
||
|
|
||
|
|
||
|
Dbg_AssertType ( &task, Tsk::Task< Skate > );
|
||
|
|
||
|
if( gamenet_man->ShouldSendScoreUpdates() == false )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(( gamenet_man->GetServer()->m_Timestamp - gamenet_man->GetLastScoreUpdateTime()) <
|
||
|
GameNet::vSCORE_UPDATE_FREQUENCY )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
mdl.SendScoreUpdates();
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Server Handlers **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* The client has requested a score event. Decide whether or not */
|
||
|
/* to allow it (don't allow it if time is up, for example), and */
|
||
|
/* relay the results back whenever we want to (which right now is */
|
||
|
/* immediately, but it doesn't have to be) */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_score_request( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgEmbedded* msg;
|
||
|
GameNet::PlayerInfo* player;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
|
||
|
msg = (GameNet::MsgEmbedded* ) context->m_Msg;
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
Mdl::Score *pScore = player->m_Skater->GetScoreObject();
|
||
|
|
||
|
switch( msg->m_SubMsgId )
|
||
|
{
|
||
|
case GameNet::SCORE_MSG_ID_LOG_TRICK_OBJECT:
|
||
|
{
|
||
|
GameNet::MsgScoreLogTrickObject* log_msg;
|
||
|
|
||
|
log_msg = (GameNet::MsgScoreLogTrickObject* ) context->m_Msg;
|
||
|
if( log_msg->m_GameId == gamenet_man->GetNetworkGameId())
|
||
|
{
|
||
|
pScore->LogTrickObject( log_msg->m_OwnerId, log_msg->m_Score, log_msg->m_NumPendingTricks, log_msg->m_PendingTrickBuffer, true );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Skater is reporting his high combo */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_combo_report( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::PlayerInfo* player;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Skate* skate_mod;
|
||
|
GameNet::MsgScoreLanded* msg;
|
||
|
|
||
|
skate_mod = (Skate*) context->m_Data;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
msg = (GameNet::MsgScoreLanded*) context->m_Msg;
|
||
|
|
||
|
// Ignore combo messages in freeskate
|
||
|
if( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x1c471c60,"netlobby"))
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
// Make sure this reported score is for this game (could be late -- could be a cheat replay packet)
|
||
|
if( gamenet_man->GetNetworkGameId() != msg->m_GameId )
|
||
|
{
|
||
|
Dbg_Printf( "Wrong game id! %d %d\n", gamenet_man->GetNetworkGameId(), msg->m_GameId );
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
// We should never get a score that's less than or equal to our recorded best combo for this
|
||
|
// player since they are only supposed to report combo scores if they eclipse their current
|
||
|
// mark. This is most-likely cheating
|
||
|
/*if( msg->m_Score <= player->m_BestCombo )
|
||
|
{
|
||
|
Dbg_Printf( "**** COMBO CHEAT DETECTED: Combo reported: %d , previous best: %d\n", msg->m_Score, player->m_BestCombo );
|
||
|
gamenet_man->CheatingOccured();
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}*/
|
||
|
|
||
|
//Dbg_Printf( "Player: %d Combo: %d\n", player->m_Skater->GetID(), msg->m_Score );
|
||
|
player->m_BestCombo = msg->m_Score;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Skater landed a trick and is reporting his score */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_landed_trick( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::PlayerInfo* player;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
int trick_score;
|
||
|
Skate* skate_mod;
|
||
|
GameNet::MsgScoreLanded* msg;
|
||
|
|
||
|
skate_mod = (Skate*) context->m_Data;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
msg = (GameNet::MsgScoreLanded*) context->m_Msg;
|
||
|
|
||
|
// Make sure this reported score is for this game (could be late -- could be a cheat replay packet)
|
||
|
if( gamenet_man->GetNetworkGameId() != msg->m_GameId )
|
||
|
{
|
||
|
Dbg_Printf( "Wrong game id! %d %d\n", gamenet_man->GetNetworkGameId(), msg->m_GameId );
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
trick_score = msg->m_Score;
|
||
|
Mdl::Score *pScore = player->m_Skater->GetScoreObject();
|
||
|
|
||
|
if( trick_score > pScore->GetBestCombo())
|
||
|
{
|
||
|
pScore->SetBestCombo( trick_score );
|
||
|
}
|
||
|
if ( !skate_mod->GetGameMode()->IsTrue("should_modulate_color") )
|
||
|
{
|
||
|
if( skate_mod->GetGameMode()->ShouldTrackTrickScore())
|
||
|
{
|
||
|
if (skate_mod->GetGameMode()->ShouldAccumulateScore())
|
||
|
{
|
||
|
pScore->SetTotalScore( pScore->GetTotalScore() + trick_score );
|
||
|
}
|
||
|
else if( skate_mod->GetGameMode()->ShouldTrackBestCombo())
|
||
|
{
|
||
|
if( pScore->GetTotalScore() < trick_score )
|
||
|
{
|
||
|
pScore->SetTotalScore( trick_score );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Skater is entering a car */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_enter_vehicle_server( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::PlayerInfo* player;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Skate* skate_mod;
|
||
|
GameNet::MsgEnterVehicle* msg;
|
||
|
|
||
|
skate_mod = (Skate*) context->m_Data;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
msg = (GameNet::MsgEnterVehicle*) context->m_Msg;
|
||
|
|
||
|
player->m_VehicleControlType = msg->m_ControlType;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Relay non-important msgs to all other clients */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_msg_relay( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
GameNet::PlayerInfo* player, *orig_player;
|
||
|
|
||
|
orig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
|
||
|
// Make sure this is from a current player
|
||
|
if( orig_player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player;
|
||
|
player = gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
// Don't relay it back to the original client
|
||
|
if( player == orig_player )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
msg_desc.m_Data = context->m_Msg;
|
||
|
msg_desc.m_Length = context->m_MsgLength;
|
||
|
msg_desc.m_Id = context->m_MsgId;
|
||
|
if( ( context->m_MsgId == GameNet::MSG_ID_BLOOD_OFF ) ||
|
||
|
( context->m_MsgId == GameNet::MSG_ID_CHAT ) ||
|
||
|
( context->m_MsgId == GameNet::MSG_ID_ENTER_VEHICLE ))
|
||
|
{
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SPAWN_PROJECTILE )
|
||
|
{
|
||
|
Skate* mod = (Skate*) context->m_Data;
|
||
|
|
||
|
if( ( mod->GetGameMode()->GetNameChecksum() == CRCD(0x3d6d444f,"firefight") ) ||
|
||
|
( mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,"netfirefight")))
|
||
|
{
|
||
|
GameNet::MsgProjectile* msg;
|
||
|
|
||
|
msg = (GameNet::MsgProjectile*) context->m_Msg;
|
||
|
if( ( msg->m_Scale <= 10.0f ) &&
|
||
|
( msg->m_Radius <= 240 ))
|
||
|
{
|
||
|
msg->m_Id = orig_player->m_Skater->GetID();
|
||
|
msg->m_Latency = context->m_Conn->GetAveLatency();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
context->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
}
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Relay script msgs to nearby clients only */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_selective_msg_relay( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
GameNet::PlayerInfo* player, *orig_player;
|
||
|
Obj::CSkater* orig_skater, *skater;
|
||
|
|
||
|
orig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
|
||
|
// Make sure this is from a current player
|
||
|
if( orig_player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
orig_skater = orig_player->m_Skater;
|
||
|
if( orig_skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player;
|
||
|
player = gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
bool send;
|
||
|
|
||
|
send = false;
|
||
|
// Don't relay it back to the original client
|
||
|
if( player != orig_player )
|
||
|
{
|
||
|
if( player->IsObserving())
|
||
|
{
|
||
|
send = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
skater = player->m_Skater;
|
||
|
if( skater )
|
||
|
{
|
||
|
Mth::Vector diff;
|
||
|
|
||
|
diff = skater->GetPos() - orig_skater->GetPos();
|
||
|
if( diff.Length() < vOBJ_UPDATE_THRESHOLD )
|
||
|
{
|
||
|
send = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( send )
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
msg_desc.m_Data = context->m_Msg;
|
||
|
msg_desc.m_Length = context->m_MsgLength;
|
||
|
msg_desc.m_Id = context->m_MsgId;
|
||
|
context->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
}
|
||
|
}
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Relay script msgs to all other clients */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_script_relay( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
GameNet::PlayerInfo* player, *orig_player;
|
||
|
|
||
|
orig_player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
|
||
|
// Make sure this is from a current player
|
||
|
if( orig_player == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player;
|
||
|
player = gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
// Don't relay it back to the original client
|
||
|
if( player == orig_player )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
msg_desc.m_Data = context->m_Msg;
|
||
|
msg_desc.m_Length = context->m_MsgLength;
|
||
|
msg_desc.m_Id = context->m_MsgId;
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
context->m_App->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
}
|
||
|
|
||
|
if( context->m_MsgId == GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT )
|
||
|
{
|
||
|
GameNet::MsgSpawnAndRunScript* msg;
|
||
|
|
||
|
msg = (GameNet::MsgSpawnAndRunScript *) context->m_Msg;
|
||
|
|
||
|
// Only save the event if it changes the level in a permanent way
|
||
|
if( msg->m_Permanent )
|
||
|
{
|
||
|
gamenet_man->AddSpawnedTriggerEvent( msg->m_Node, msg->m_ObjID, msg->m_ScriptName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Relay non-important msgs to all other clients */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_bail_done( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* player;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( player )
|
||
|
{
|
||
|
player->ClearNonCollidable();
|
||
|
}
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Change levels */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_change_level( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* skate;
|
||
|
skate = (Skate*)context->m_Data;
|
||
|
|
||
|
GameNet::MsgChangeLevel* pMsg;
|
||
|
pMsg = (GameNet::MsgChangeLevel*) context->m_Msg;
|
||
|
|
||
|
skate->ChangeLevel( pMsg->m_Level );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Receive and store client skater states for relay later on */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_object_update( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Obj::CSkater* skater;
|
||
|
GameNet::PlayerInfo* player;
|
||
|
int i, index, last_index;
|
||
|
unsigned int timestamp;
|
||
|
char state, doing_trick, terrain, walking, driving;
|
||
|
Flags< int > skater_flags;
|
||
|
Flags< int > end_run_flags;
|
||
|
short pos[3];
|
||
|
Mth::Vector eulers;
|
||
|
sint16 rail_node;
|
||
|
short fixed;
|
||
|
int update_flags;
|
||
|
Obj::SPosEvent* latest_state, *previous_state;
|
||
|
Net::BitStream stream;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
|
||
|
// Ignore late/foreign updates and update from non-ready/non-existent clients
|
||
|
if( ( player == NULL ) ||
|
||
|
( player->m_Conn->TestStatus( Net::Conn::mSTATUS_READY ) == false ) ||
|
||
|
( context->m_PacketFlags & ( Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN )))
|
||
|
{
|
||
|
int size, value, bit_data;
|
||
|
|
||
|
size = 0;
|
||
|
bit_data = 0;
|
||
|
|
||
|
// Even though we don't process the data, we need to calculate the msg length
|
||
|
// so that dispatcher knows how many bytes to skip
|
||
|
stream.SetInputData( context->m_Msg, 1024 );
|
||
|
|
||
|
bit_data += sizeof( int ) * 8; // Timestamp size
|
||
|
value = stream.ReadSignedValue( sizeof( int ) * 8 );
|
||
|
update_flags = stream.ReadUnsignedValue( 9 );
|
||
|
bit_data += 9;
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_X )
|
||
|
{
|
||
|
//bit_data += sizeof( float ) * 8;
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Y )
|
||
|
{
|
||
|
//bit_data += sizeof( float ) * 8;
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Z )
|
||
|
{
|
||
|
//bit_data += sizeof( float ) * 8;
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_X )
|
||
|
{
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )
|
||
|
{
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )
|
||
|
{
|
||
|
bit_data += sizeof( short ) * 8;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_STATE )
|
||
|
{
|
||
|
bit_data += 12;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_FLAGS )
|
||
|
{
|
||
|
bit_data += 5;
|
||
|
bit_data += 3;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )
|
||
|
{
|
||
|
bit_data += 16;
|
||
|
}
|
||
|
|
||
|
size += (( bit_data + 7 ) >> 3 );
|
||
|
|
||
|
context->m_MsgLength = size;
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
skater = player->m_Skater;
|
||
|
if( skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
index = skater->GetStateHistory()->GetNumPosUpdates() % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
latest_state = &skater->GetStateHistory()->GetPosHistory()[index];
|
||
|
previous_state = NULL;
|
||
|
|
||
|
if( skater->GetStateHistory()->GetNumPosUpdates() > 0 )
|
||
|
{
|
||
|
last_index = ( skater->GetStateHistory()->GetNumPosUpdates() + ( Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS - 1 )) %
|
||
|
Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
previous_state = &skater->GetStateHistory()->GetPosHistory()[last_index];
|
||
|
|
||
|
doing_trick = previous_state->DoingTrick;
|
||
|
state = previous_state->State;
|
||
|
skater_flags = previous_state->SkaterFlags;
|
||
|
end_run_flags = previous_state->EndRunFlags;
|
||
|
terrain = previous_state->Terrain;
|
||
|
walking = previous_state->Walking;
|
||
|
driving = previous_state->Driving;
|
||
|
rail_node = previous_state->RailNode;
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
pos[i] = previous_state->ShortPos[i];
|
||
|
}
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
eulers[i] = previous_state->Eulers[i];
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
doing_trick = 0;
|
||
|
state = 0;
|
||
|
skater_flags = 0;
|
||
|
end_run_flags = 0;
|
||
|
terrain = 0;
|
||
|
walking = 0;
|
||
|
driving = 0;
|
||
|
rail_node = -1;
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
pos[i] = 0;
|
||
|
}
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
eulers[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
stream.SetInputData( context->m_Msg, 1024 );
|
||
|
|
||
|
// Read in timestamp
|
||
|
timestamp = stream.ReadUnsignedValue( sizeof( int ) * 8 );
|
||
|
update_flags = stream.ReadUnsignedValue( 9 );
|
||
|
|
||
|
// Read in fixed point position
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_X )
|
||
|
{
|
||
|
pos[X] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[X] = stream.ReadFloatValue();
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Y )
|
||
|
{
|
||
|
pos[Y] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[Y] = stream.ReadFloatValue();
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Z )
|
||
|
{
|
||
|
pos[Z] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[Z] = stream.ReadFloatValue();
|
||
|
}
|
||
|
|
||
|
// Read in fixed point eulers
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_X )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[X] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[Y] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[Z] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
|
||
|
// Read in skater's 'state'
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_STATE )
|
||
|
{
|
||
|
char mask;
|
||
|
|
||
|
mask = stream.ReadUnsignedValue( 4 );
|
||
|
|
||
|
state = mask & GameNet::mSTATE_MASK;
|
||
|
doing_trick = (( mask & GameNet::mDOING_TRICK_MASK ) != 0 );
|
||
|
|
||
|
terrain = stream.ReadUnsignedValue( 6 );
|
||
|
|
||
|
walking = stream.ReadUnsignedValue( 1 );
|
||
|
driving = stream.ReadUnsignedValue( 1 );
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_FLAGS )
|
||
|
{
|
||
|
skater_flags = stream.ReadUnsignedValue( 5 );
|
||
|
end_run_flags = stream.ReadUnsignedValue( 3 );
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )
|
||
|
{
|
||
|
rail_node = stream.ReadSignedValue( sizeof( sint16 ) * 8 );
|
||
|
}
|
||
|
|
||
|
|
||
|
// Tell the dispatcher the size of this message because it does not know (optimization)
|
||
|
context->m_MsgLength = stream.GetByteLength();
|
||
|
|
||
|
if( ( skater->GetStateHistory()->GetNumPosUpdates() > 0 ) &&
|
||
|
( timestamp < previous_state->GetTime()))
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
// Use those euler angles to compose a matrix
|
||
|
Mth::Matrix obj_matrix( eulers[X], eulers[Y], eulers[Z] );
|
||
|
|
||
|
latest_state->Matrix = obj_matrix;
|
||
|
latest_state->Position.Set( ((float) pos[X] ) / 2.0f,//pos[X],
|
||
|
((float) pos[Y] ) / 4.0f,//pos[Y],
|
||
|
((float) pos[Z] ) / 2.0f,//pos[Z],
|
||
|
0.0f );
|
||
|
|
||
|
latest_state->SetTime( timestamp );
|
||
|
|
||
|
// Update short versions in the player history
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
latest_state->ShortPos[i] = pos[i];
|
||
|
latest_state->Eulers[i] = eulers[i];
|
||
|
}
|
||
|
|
||
|
latest_state->DoingTrick = doing_trick;
|
||
|
latest_state->SkaterFlags = skater_flags;
|
||
|
latest_state->EndRunFlags = end_run_flags;
|
||
|
latest_state->State = state;
|
||
|
latest_state->Terrain = (ETerrainType) terrain;
|
||
|
latest_state->RailNode = rail_node;
|
||
|
latest_state->Walking = walking;
|
||
|
latest_state->Driving = driving;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumPosUpdates();
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Client Handlers **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Execute a script */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_run_script( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
GameNet::MsgRunScript* msg;
|
||
|
Script::CScriptStructure *pParams;
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
msg = (GameNet::MsgRunScript *) context->m_Msg;
|
||
|
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjID );
|
||
|
|
||
|
pParams = new Script::CScriptStructure;
|
||
|
Script::ReadFromBuffer(pParams,(uint8 *) msg->m_Data );
|
||
|
|
||
|
Script::RunScript( msg->m_ScriptName, pParams, obj );
|
||
|
|
||
|
delete pParams;
|
||
|
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Spawn and run a script */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_spawn_run_script( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
Script::CScript* pScript;
|
||
|
Obj::CMovingObject* obj;
|
||
|
GameNet::MsgSpawnAndRunScript* msg;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
msg = (GameNet::MsgSpawnAndRunScript *) context->m_Msg;
|
||
|
|
||
|
if( gamenet_man->ReadyToPlay())
|
||
|
{
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjID );
|
||
|
|
||
|
pScript = Script::SpawnScript( msg->m_ScriptName, NULL, 0, NULL, msg->m_Node ); // K: The 0,NULL bit means no callback script specified
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
pScript->SetCommentString("Spawned from Skate::handle_spawn_run_script");
|
||
|
#endif
|
||
|
pScript->mpObject = obj;
|
||
|
|
||
|
pScript->Update();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gamenet_man->AddSpawnedTriggerEvent( msg->m_Node, msg->m_ObjID, msg->m_ScriptName );
|
||
|
}
|
||
|
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Unpacks wobble details */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
static float s_get_wobble_details_from_mask( char mask, int field )
|
||
|
{
|
||
|
float value;
|
||
|
|
||
|
value = 0;
|
||
|
switch( field )
|
||
|
{
|
||
|
case GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A:
|
||
|
{
|
||
|
int field_mask;
|
||
|
|
||
|
field_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_AMPA_MASK;
|
||
|
if( field_mask == 0 )
|
||
|
{
|
||
|
value = 0.05f;
|
||
|
}
|
||
|
else if( field_mask == 1 )
|
||
|
{
|
||
|
value = 0.1f;
|
||
|
}
|
||
|
else if( field_mask == 2 )
|
||
|
{
|
||
|
value = 10.1f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Assert( 0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B:
|
||
|
{
|
||
|
int field_mask;
|
||
|
|
||
|
field_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_AMPB_MASK;
|
||
|
field_mask >>= 2;
|
||
|
if( field_mask == 0 )
|
||
|
{
|
||
|
value = 0.04f;
|
||
|
}
|
||
|
else if( field_mask == 1 )
|
||
|
{
|
||
|
value = 10.1f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Assert( 0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case GameNet::MsgSetWobbleDetails::vWOBBLE_K1:
|
||
|
{
|
||
|
int field_mask;
|
||
|
|
||
|
field_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_K1_MASK;
|
||
|
field_mask >>= 3;
|
||
|
if( field_mask == 0 )
|
||
|
{
|
||
|
value = 0.0022f;
|
||
|
}
|
||
|
else if( field_mask == 1 )
|
||
|
{
|
||
|
value = 20.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Assert( 0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case GameNet::MsgSetWobbleDetails::vWOBBLE_K2:
|
||
|
{
|
||
|
int field_mask;
|
||
|
|
||
|
field_mask = mask & GameNet::MsgSetWobbleDetails::mWOBBLE_K2_MASK;
|
||
|
field_mask >>= 4;
|
||
|
if( field_mask == 0 )
|
||
|
{
|
||
|
value = 0.0017f;
|
||
|
}
|
||
|
else if( field_mask == 1 )
|
||
|
{
|
||
|
value = 10.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Assert( 0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case GameNet::MsgSetWobbleDetails::vSPAZFACTOR:
|
||
|
{
|
||
|
int field_mask;
|
||
|
|
||
|
field_mask = mask & GameNet::MsgSetWobbleDetails::mSPAZFACTOR_MASK;
|
||
|
field_mask >>= 5;
|
||
|
if( field_mask == 0 )
|
||
|
{
|
||
|
value = 1.5f;
|
||
|
}
|
||
|
else if( field_mask == 1 )
|
||
|
{
|
||
|
value = 1.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Assert( 0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
Dbg_Assert( 0 );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* A client has launched a projectile */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_projectile( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgProjectile* msg;
|
||
|
Script::CStruct* pParams;
|
||
|
Obj::CSkater* skater;
|
||
|
Skate* mod;
|
||
|
Mth::Vector vel, dir, pos;
|
||
|
Tmr::Time lag;
|
||
|
float time;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
|
||
|
msg = (GameNet::MsgProjectile*) context->m_Msg;
|
||
|
skater = mod->GetSkaterById( msg->m_Id );
|
||
|
if( skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
vel = msg->m_Vel;
|
||
|
pos = msg->m_Pos;
|
||
|
dir = vel;
|
||
|
dir.Normalize();
|
||
|
lag = msg->m_Latency;
|
||
|
|
||
|
// If not on the server, also add the average latency from server to us
|
||
|
if( gamenet_man->OnServer() == false )
|
||
|
{
|
||
|
Lst::Search< Net::Conn > sh;
|
||
|
Net::Conn* server_conn;
|
||
|
|
||
|
server_conn = context->m_App->FirstConnection( &sh );
|
||
|
lag += server_conn->GetAveLatency();
|
||
|
}
|
||
|
|
||
|
time = (float) lag / 1000.0f;
|
||
|
pos += dir * time; // Time is in units of seconds. Velocity is in terms of feet/sec
|
||
|
|
||
|
pParams = new Script::CStruct;
|
||
|
pParams->AddChecksum( CRCD(0x81c39e06,"owner_id"), msg->m_Id );
|
||
|
pParams->AddInteger( CRCD(0x7323e97c,"x"), pos[X] );
|
||
|
pParams->AddInteger( CRCD(0x424d9ea,"y"), pos[Y] );
|
||
|
pParams->AddInteger( CRCD(0x9d2d8850,"z"), pos[Z] );
|
||
|
pParams->AddInteger( CRCD(0xbded7a76,"scaled_x"), msg->m_Vel[X] );
|
||
|
pParams->AddInteger( CRCD(0xcaea4ae0,"scaled_y"), msg->m_Vel[Y] );
|
||
|
pParams->AddInteger( CRCD(0x53e31b5a,"scaled_z"), msg->m_Vel[Z] );
|
||
|
pParams->AddInteger( CRCD(0xc48391a5,"radius"), msg->m_Radius );
|
||
|
pParams->AddFloat( CRCD(0x13b9da7b,"scale"), msg->m_Scale );
|
||
|
|
||
|
Script::RunScript( CRCD(0xaa2b5552,"ClientLaunchFireball"), pParams, skater );
|
||
|
delete pParams;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* A client has entered a vehicle */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_enter_vehicle_client( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgEnterVehicle* msg;
|
||
|
Obj::CSkater* skater;
|
||
|
Skate* mod;
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
|
||
|
msg = (GameNet::MsgEnterVehicle*) context->m_Msg;
|
||
|
skater = mod->GetSkaterById( msg->m_Id );
|
||
|
if( skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
Dbg_Assert(GetSkaterStateHistoryComponentFromObject(skater));
|
||
|
GetSkaterStateHistoryComponentFromObject(skater)->SetCurrentVehicleControlType(msg->m_ControlType);
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* The server has sent a list of cheats that are enabled */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_cheat_list( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgEnabledCheats* msg;
|
||
|
int i;
|
||
|
|
||
|
Dbg_Printf( "**** HANDLING CHEAT LIST\n" );
|
||
|
CFuncs::ScriptClearCheats( NULL, NULL );
|
||
|
|
||
|
msg = (GameNet::MsgEnabledCheats*) context->m_Msg;
|
||
|
for( i = 0; i < msg->m_NumCheats; i++ )
|
||
|
{
|
||
|
Script::CStruct* pParams;
|
||
|
|
||
|
pParams = new Script::CStruct;
|
||
|
pParams->AddChecksum( CRCD(0xf649d637,"on"), 0 );
|
||
|
pParams->AddChecksum( CRCD(0xae94c183,"cheat_flag"), msg->m_Cheats[i] );
|
||
|
Script::RunScript( CRCD(0x3cf9e86d,"client_toggle_cheat"), pParams );
|
||
|
|
||
|
delete pParams;
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* The server has toggled a cheat. Mimic behavior on this end */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_cheats( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgToggleCheat* msg;
|
||
|
Script::CStruct* pParams;
|
||
|
|
||
|
pParams = new Script::CStruct;
|
||
|
msg = (GameNet::MsgToggleCheat*) context->m_Msg;
|
||
|
|
||
|
if( msg->m_On )
|
||
|
{
|
||
|
pParams->AddChecksum( CRCD(0xf649d637,"on"), 0 );
|
||
|
}
|
||
|
|
||
|
pParams->AddChecksum( CRCD(0xae94c183,"cheat_flag"), msg->m_Cheat );
|
||
|
|
||
|
Script::RunScript( CRCD(0x3cf9e86d,"client_toggle_cheat"), pParams );
|
||
|
|
||
|
delete pParams;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Get the number of times the 16-bit value was flipped since the */
|
||
|
/* last time */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int s_get_num_flips( uint32 new_time, uint32 old_time )
|
||
|
{
|
||
|
uint32 hi_new, hi_old;
|
||
|
|
||
|
hi_new = new_time >> 16;
|
||
|
hi_old = old_time >> 16;
|
||
|
|
||
|
return ( hi_new - hi_old );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Animate non-local clients */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_anims( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Obj::SAnimEvent* latest_event;
|
||
|
Obj::CMovingObject* obj;
|
||
|
Obj::CSkater* skater;
|
||
|
Skate* mod;
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
if( context->m_MsgId == GameNet::MSG_ID_PRIM_ANIM_START )
|
||
|
{
|
||
|
GameNet::MsgPlayPrimaryAnim anim_msg;
|
||
|
char* stream;
|
||
|
|
||
|
stream = context->m_Msg;
|
||
|
|
||
|
//memcpy( &anim_msg.m_Time, stream, sizeof( unsigned short ));
|
||
|
//Dbg_Printf( "(%d) Got Primary %d\n", context->m_App->m_FrameCounter, anim_msg.m_Time );
|
||
|
//stream += sizeof( int );
|
||
|
memcpy( &anim_msg.m_LoopingType, stream, sizeof( char ));
|
||
|
stream++;
|
||
|
memcpy( &anim_msg.m_ObjId, stream, sizeof( char ));
|
||
|
stream++;
|
||
|
memcpy( &anim_msg.m_Index, stream, sizeof( uint32 ));
|
||
|
stream += sizeof( uint32 );
|
||
|
memcpy( &anim_msg.m_StartTime, stream, sizeof( unsigned short ));
|
||
|
stream += sizeof( unsigned short );
|
||
|
memcpy( &anim_msg.m_EndTime, stream, sizeof( unsigned short ));
|
||
|
stream += sizeof( unsigned short );
|
||
|
memcpy( &anim_msg.m_BlendPeriod, stream, sizeof( unsigned short ));
|
||
|
stream += sizeof( unsigned short );
|
||
|
memcpy( &anim_msg.m_Speed, stream, sizeof( unsigned short ));
|
||
|
stream += sizeof( unsigned short );
|
||
|
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( anim_msg.m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
float blend_period;
|
||
|
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
blend_period = (float) anim_msg.m_BlendPeriod / 4096.0f;
|
||
|
|
||
|
// Only blend skaters that we are observing
|
||
|
if ( gamenet_man->InNetGame() )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* observed_player, *anim_player;
|
||
|
|
||
|
anim_player = gamenet_man->GetPlayerByObjectID( obj->GetID() );
|
||
|
observed_player = gamenet_man->GetCurrentlyObservedPlayer();
|
||
|
if(( observed_player == NULL ) || ( anim_player != observed_player ))
|
||
|
{
|
||
|
blend_period = 0.0f;
|
||
|
}
|
||
|
}
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_PRIM_ANIM_START;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Setting anm time: %d\n", context->m_App->m_FrameCounter, latest_event->GetTime());
|
||
|
|
||
|
latest_event->m_ObjId = anim_msg.m_ObjId;
|
||
|
latest_event->m_Asset = anim_msg.m_Index;
|
||
|
latest_event->m_StartTime = (float) anim_msg.m_StartTime / 4096.0f;
|
||
|
latest_event->m_EndTime = (float) anim_msg.m_EndTime / 4096.0f;
|
||
|
latest_event->m_BlendPeriod = blend_period;
|
||
|
latest_event->m_Speed = (float) anim_msg.m_Speed / 4096.0f;
|
||
|
latest_event->m_LoopingType = anim_msg.m_LoopingType;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SET_WOBBLE_TARGET )
|
||
|
{
|
||
|
GameNet::MsgSetWobbleTarget* msg;
|
||
|
|
||
|
msg = (GameNet::MsgSetWobbleTarget *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_SET_WOBBLE_TARGET;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got Wobble %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Alpha = (float) msg->m_Alpha / 255.0f;
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_ROTATE_SKATEBOARD )
|
||
|
{
|
||
|
GameNet::MsgRotateSkateboard* msg;
|
||
|
|
||
|
msg = (GameNet::MsgRotateSkateboard *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_ROTATE_SKATEBOARD;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got Rotate %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Rotate = msg->m_Rotate;
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SET_WOBBLE_DETAILS )
|
||
|
{
|
||
|
GameNet::MsgSetWobbleDetails* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgSetWobbleDetails *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_SET_WOBBLE_DETAILS;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got details %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_WobbleAmpA = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_A );
|
||
|
latest_event->m_WobbleAmpB = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_AMP_B );
|
||
|
latest_event->m_WobbleK1 = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_K1 );
|
||
|
latest_event->m_WobbleK2 = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vWOBBLE_K2 );
|
||
|
latest_event->m_SpazFactor = s_get_wobble_details_from_mask( msg->m_WobbleDetails, GameNet::MsgSetWobbleDetails::vSPAZFACTOR );
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SET_LOOPING_TYPE )
|
||
|
{
|
||
|
GameNet::MsgSetLoopingType* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgSetLoopingType *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_SET_LOOPING_TYPE;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got looping %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_LoopingType = msg->m_LoopingType;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SET_HIDE_ATOMIC )
|
||
|
{
|
||
|
GameNet::MsgHideAtomic* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgHideAtomic *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_SET_HIDE_ATOMIC;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Asset = msg->m_AtomicName;
|
||
|
latest_event->m_Hide = msg->m_Hide;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_SET_ANIM_SPEED )
|
||
|
{
|
||
|
GameNet::MsgSetAnimSpeed* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgSetAnimSpeed *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater != NULL,( "Got anim for non-CSkater" ));
|
||
|
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_SET_ANIM_SPEED;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got speed %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Speed = msg->m_AnimSpeed;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_FLIP_ANIM )
|
||
|
{
|
||
|
GameNet::MsgFlipAnim* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgFlipAnim *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = mod->GetSkaterById( msg->m_ObjId );
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_FLIP_ANIM;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got flip %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_Flipped = msg->m_Flipped;
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
|
||
|
// If we got a flip message for a skater, we've now handled it. Otherwise,
|
||
|
// let it fall through as it is for some other object in the game
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_ROTATE_DISPLAY )
|
||
|
{
|
||
|
GameNet::MsgRotateDisplay* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgRotateDisplay *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = mod->GetSkaterById( msg->m_ObjId );
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_ROTATE_DISPLAY;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
//Dbg_Printf( "(%d) Got rotate %d\n", context->m_App->m_FrameCounter, msg->m_Time );
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Duration = msg->m_Duration;
|
||
|
latest_event->m_SinePower = msg->m_SinePower;
|
||
|
latest_event->m_StartAngle = msg->m_StartAngle;
|
||
|
latest_event->m_DeltaAngle = msg->m_DeltaAngle;
|
||
|
latest_event->m_HoldOnLastAngle = msg->m_HoldOnLastAngle;
|
||
|
latest_event->m_Flags = msg->m_Flags;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY )
|
||
|
{
|
||
|
GameNet::MsgObjMessage* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
|
||
|
msg = (GameNet::MsgObjMessage *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = mod->GetSkaterById( msg->m_ObjId );
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_CREATE_SPECIAL_ITEM )
|
||
|
{
|
||
|
Obj::CMovingObject* obj;
|
||
|
GameNet::MsgSpecialItem* msg;
|
||
|
|
||
|
msg = (GameNet::MsgSpecialItem *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = mod->GetSkaterById( msg->m_ObjId );
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_CREATE_SPECIAL_ITEM;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Bone = msg->m_Bone;
|
||
|
latest_event->m_Index = msg->m_Index;
|
||
|
latest_event->m_Asset = msg->m_Params;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_DESTROY_SPECIAL_ITEM )
|
||
|
{
|
||
|
Obj::CMovingObject* obj;
|
||
|
GameNet::MsgSpecialItem* msg;
|
||
|
|
||
|
msg = (GameNet::MsgSpecialItem *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
skater = mod->GetSkaterById( msg->m_ObjId );
|
||
|
if( skater )
|
||
|
{
|
||
|
latest_event = skater->GetStateHistory()->GetLatestAnimEvent();
|
||
|
latest_event->m_MsgId = GameNet::MSG_ID_DESTROY_SPECIAL_ITEM;
|
||
|
latest_event->SetTime( skater->GetStateHistory()->GetLastPosEvent()->GetTime());
|
||
|
latest_event->m_ObjId = msg->m_ObjId;
|
||
|
latest_event->m_Index = msg->m_Index;
|
||
|
|
||
|
skater->GetStateHistory()->IncrementNumAnimUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_flip_anim( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
|
||
|
GameNet::MsgFlipAnim* msg;
|
||
|
|
||
|
Obj::CMovingObject* obj;
|
||
|
msg = (GameNet::MsgFlipAnim *) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
Obj::CMovingObject* moving_obj;
|
||
|
|
||
|
moving_obj = static_cast< Obj::CMovingObject *> ( obj );
|
||
|
Dbg_MsgAssert( moving_obj != NULL,( "Got object update for non-CMovingObj\n" ));
|
||
|
|
||
|
if( moving_obj )
|
||
|
{
|
||
|
Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( moving_obj );
|
||
|
if ( pAnimationComponent )
|
||
|
{
|
||
|
pAnimationComponent->FlipAnimation( msg->m_ObjId, msg->m_Flipped, context->m_App->m_Timestamp, false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_player_quit( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::PlayerInfo* player;
|
||
|
Skate* mod;
|
||
|
GameNet::MsgPlayerQuit* msg;
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
|
||
|
Dbg_Printf( "Got player quit message" );
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
msg = (GameNet::MsgPlayerQuit *) context->m_Msg;
|
||
|
player = gamenet_man->GetPlayerByObjectID( msg->m_ObjId );
|
||
|
if( player )
|
||
|
{
|
||
|
Obj::CSkater* quitting_skater;
|
||
|
|
||
|
quitting_skater = player->m_Skater;
|
||
|
|
||
|
Dbg_Printf( "Got player quit message 2" );
|
||
|
gamenet_man->DropPlayer( player, (GameNet::DropReason) msg->m_Reason );
|
||
|
mod->remove_skater( quitting_skater );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GameNet::NewPlayerInfo* pending_player;
|
||
|
|
||
|
pending_player = gamenet_man->GetNewPlayerInfoByObjectID( msg->m_ObjId );
|
||
|
if( pending_player )
|
||
|
{
|
||
|
gamenet_man->DestroyNewPlayer( pending_player );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// The server may have been waiting for us to load this player. If so, tell the server we're ready now.
|
||
|
gamenet_man->RespondToReadyQuery();
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
#if 0
|
||
|
static bool HostQuitDialogHandler( Front::EDialogBoxResult result )
|
||
|
{
|
||
|
|
||
|
|
||
|
if( result == Front::DB_OK )
|
||
|
{
|
||
|
Mdl::FrontEnd* front = Mdl::FrontEnd::Instance();
|
||
|
|
||
|
Script::RunScript( "chosen_leave_server" );
|
||
|
front->PauseGame( false );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_disconn_accepted( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
|
||
|
|
||
|
Dbg_Message( "Logging off of server\n" );
|
||
|
|
||
|
Script::RunScript( "CreateServerQuitDialog" );
|
||
|
gamenet_man->CleanupPlayers();
|
||
|
gamenet_man->ClientShutdown();
|
||
|
|
||
|
return Net::HANDLER_HALT;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* You've been kicked by the server */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_kicked( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Skate * skate_mod = Skate::Instance();
|
||
|
|
||
|
|
||
|
|
||
|
Dbg_Message( "Logging off of server\n" );
|
||
|
|
||
|
Script::DeleteSpawnedScripts();
|
||
|
|
||
|
Script::CScriptStructure* pStructure = new Script::CScriptStructure;
|
||
|
|
||
|
pStructure->AddComponent( Script::GenerateCRC( "width" ), ESYMBOLTYPE_INTEGER, 300 );
|
||
|
pStructure->AddComponent( Script::GenerateCRC( "title" ), ESYMBOLTYPE_NAME, (int) Script::GenerateCRC("net_notice_msg"));
|
||
|
if( context->m_MsgId == GameNet::MSG_ID_KICKED )
|
||
|
{
|
||
|
Script::RunScript( "CreateServerRemovedYouDialog" );
|
||
|
}
|
||
|
else if( context->m_MsgId == GameNet::MSG_ID_LEFT_OUT )
|
||
|
{
|
||
|
Script::RunScript( "CreateServerMovedOnDialog" );
|
||
|
}
|
||
|
|
||
|
if( skate_mod->m_requested_level == Script::GenerateCRC( "load_skateshop" ))
|
||
|
{
|
||
|
// If we got partially in, cancel the join and remove partially-loaded players
|
||
|
// Shut the client down so that it doesn't bombard the server ip with messages
|
||
|
gamenet_man->CancelJoinServer();
|
||
|
gamenet_man->SetJoinState( GameNet::vJOIN_STATE_FINISHED );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gamenet_man->CleanupPlayers();
|
||
|
gamenet_man->ClientShutdown();
|
||
|
}
|
||
|
|
||
|
delete pStructure;
|
||
|
|
||
|
return Net::HANDLER_HALT;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Observer-specific trick object handling */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_obs_log_trick_objects( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::MsgObsScoreLogTrickObject* msg;
|
||
|
Skate* skate_mod;
|
||
|
|
||
|
skate_mod = (Skate*) context->m_Data;
|
||
|
msg = (GameNet::MsgObsScoreLogTrickObject*) context->m_Msg;
|
||
|
|
||
|
if( msg->m_GameId != gamenet_man->GetNetworkGameId())
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
int seq;
|
||
|
|
||
|
if( skate_mod->GetGameMode()->IsTeamGame())
|
||
|
{
|
||
|
GameNet::PlayerInfo* player;
|
||
|
|
||
|
player = gamenet_man->GetPlayerByObjectID( msg->m_OwnerId );
|
||
|
seq = player->m_Team;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
seq = msg->m_OwnerId;
|
||
|
}
|
||
|
|
||
|
// modulate the color here
|
||
|
for( uint32 i = 0; i < msg->m_NumPendingTricks; i++ )
|
||
|
{
|
||
|
skate_mod->GetTrickObjectManager()->ModulateTrickObjectColor( msg->m_PendingTrickBuffer[i], seq );
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* handle custom face data */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_face_data( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::PlayerInfo* sender;
|
||
|
Obj::CSkater* skater;
|
||
|
uint8* face_data;
|
||
|
int face_data_length;
|
||
|
uint8 skater_id;
|
||
|
|
||
|
Dbg_Printf( "**** HANDLING FACE DATA****" );
|
||
|
|
||
|
// Create a new temporary CFaceTexture.
|
||
|
Gfx::CFaceTexture* pFaceTexture = new Gfx::CFaceTexture;
|
||
|
|
||
|
face_data = (uint8*) context->m_Msg;
|
||
|
face_data_length = context->m_MsgLength;
|
||
|
skater_id = 0;
|
||
|
if( gamenet_man->OnServer())
|
||
|
{
|
||
|
sender = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
if( sender == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
skater = sender->m_Skater;
|
||
|
if( skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
skater_id = *face_data++;
|
||
|
face_data_length -= sizeof( char );
|
||
|
|
||
|
sender = gamenet_man->GetPlayerByObjectID( skater_id );
|
||
|
if( sender == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
skater = sender->m_Skater;
|
||
|
if( skater == NULL )
|
||
|
{
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Read in data from network message
|
||
|
pFaceTexture->ReadFromBuffer((uint8*) face_data, face_data_length );
|
||
|
pFaceTexture->SetValid( true );
|
||
|
|
||
|
// Get the skater's model
|
||
|
Obj::CModelComponent* pModelComponent = GetModelComponentFromObject( skater );
|
||
|
Dbg_Assert( pModelComponent );
|
||
|
Nx::CModel* pModel = pModelComponent->GetModel();
|
||
|
Dbg_Assert( pModel );
|
||
|
|
||
|
// Apply face texture to new model (eventually these parameters
|
||
|
// might need to come through the same network message,
|
||
|
// depending on the sex of the skater)
|
||
|
const char* pSrcTexture = "CS_NSN_facemap.png";
|
||
|
pModel->ApplyFaceTexture( pFaceTexture, pSrcTexture, Nx::CModel::vREPLACE_GLOBALLY );
|
||
|
|
||
|
if( gamenet_man->OnServer())
|
||
|
{
|
||
|
GameNet::PlayerInfo* face_player, *player;
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
Net::Server* server;
|
||
|
|
||
|
server = (Net::Server*) context->m_App;
|
||
|
|
||
|
// need to copy face texture data somewhere
|
||
|
// so that future joining players can get
|
||
|
// everyone else's face textures (unimplemented)
|
||
|
face_player = gamenet_man->GetPlayerByConnection( context->m_Conn );
|
||
|
face_player->SetFaceData((uint8*) context->m_Msg, context->m_MsgLength );
|
||
|
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))
|
||
|
{
|
||
|
if( player->IsLocalPlayer() || ( player == face_player ))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
server->StreamMessageToConn( player->m_Conn, GameNet::MSG_ID_FACE_DATA, Gfx::CFaceTexture::vTOTAL_CFACETEXTURE_SIZE + 1, face_player->GetFaceData(), "Face Data",
|
||
|
GameNet::vSEQ_GROUP_FACE_MSGS, false, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete pFaceTexture;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Observer-specific trick object handling */
|
||
|
/* for when the level starts up (observer needs to "catch up" */
|
||
|
/* to everyone else's trick object state) */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_obs_init_graffiti_state( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
|
||
|
|
||
|
GameNet::MsgInitGraffitiState* msg;
|
||
|
Skate* skate_mod;
|
||
|
int i;
|
||
|
|
||
|
skate_mod = (Skate*) context->m_Data;
|
||
|
msg = (GameNet::MsgInitGraffitiState*) context->m_Msg;
|
||
|
|
||
|
if ( !skate_mod->GetGameMode()->IsTrue( "should_modulate_color" ) )
|
||
|
{
|
||
|
printf( "No need to continue cause we're not in graffiti mode" );
|
||
|
|
||
|
// no need to process the msg here unless it's graffiti mode
|
||
|
return Net::HANDLER_MSG_DONE;
|
||
|
}
|
||
|
|
||
|
uint8* pStartOfStream = &msg->m_TrickObjectStream[0];
|
||
|
|
||
|
Obj::CTrickObjectManager* pTrickObjectManager = skate_mod->GetTrickObjectManager();
|
||
|
Dbg_Assert( pTrickObjectManager );
|
||
|
|
||
|
// push heap
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().ScriptHeap());
|
||
|
|
||
|
Script::CScriptStructure* pStructure = new Script::CScriptStructure;
|
||
|
|
||
|
// modulate the color here
|
||
|
for( i = 0; i < vMAX_SKATERS; i++ )
|
||
|
{
|
||
|
if ( msg->m_NumTrickObjects[i] )
|
||
|
{
|
||
|
Script::CArray* pArray = new Script::CArray;
|
||
|
|
||
|
pArray->SetArrayType( msg->m_NumTrickObjects[i], ESYMBOLTYPE_NAME );
|
||
|
|
||
|
for ( int j = 0; j < msg->m_NumTrickObjects[i]; j++ )
|
||
|
{
|
||
|
uint32 trick_object_checksum = pTrickObjectManager->GetUncompressedTrickObjectChecksum( *pStartOfStream );
|
||
|
pArray->SetChecksum( j, trick_object_checksum );
|
||
|
// pTrickObjectManager->ModulateTrickObjectColor( trick_object_checksum, i );
|
||
|
pStartOfStream++;
|
||
|
}
|
||
|
|
||
|
char arrayName[32];
|
||
|
sprintf( arrayName, "Skater%d", i );
|
||
|
pStructure->AddComponent( Script::GenerateCRC( arrayName ), pArray );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pTrickObjectManager->SetObserverGraffitiState( pStructure );
|
||
|
pTrickObjectManager->ApplyObserverGraffitiState();
|
||
|
|
||
|
delete pStructure;
|
||
|
|
||
|
// apply color modulation a few frames later...
|
||
|
//
|
||
|
//
|
||
|
// This was never defined, so I commented it out. I just apply it immediately and this
|
||
|
// seems to work for now
|
||
|
//Script::SpawnScript( "deferred_observer_trick_modulation", pStructure, 0, NULL );
|
||
|
|
||
|
// pop heap
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Set terrain type */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_score_update( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
|
||
|
Mdl::FrontEnd* front_end = Mdl::FrontEnd::Instance();
|
||
|
GameNet::MsgScoreUpdate* msg;
|
||
|
Obj::CMovingObject *obj;
|
||
|
Skate* mod;
|
||
|
int i, score;
|
||
|
char* data;
|
||
|
char id;
|
||
|
|
||
|
msg = (GameNet::MsgScoreUpdate*) context->m_Msg;
|
||
|
data = msg->m_ScoreData;
|
||
|
mod = (Skate*) context->m_Data;
|
||
|
|
||
|
if( !gamenet_man->OnServer())
|
||
|
{
|
||
|
mod->GetGameMode()->SetTimeLeft( msg->m_TimeLeft );
|
||
|
}
|
||
|
|
||
|
for( i = 0; i < msg->m_NumScores; i++ )
|
||
|
{
|
||
|
id = *data;
|
||
|
data++;
|
||
|
memcpy( &score, data, sizeof( int ));
|
||
|
data += sizeof( int );
|
||
|
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( id );
|
||
|
if( obj )
|
||
|
{
|
||
|
Obj::CSkater* skater_obj;
|
||
|
|
||
|
skater_obj = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater_obj != NULL,( "Got score update for non-CSkater\n" ));
|
||
|
|
||
|
if( ( mod->GetGameMode()->IsTrue( "should_modulate_color" )) ||
|
||
|
( mod->GetGameMode()->ShouldTrackTrickScore() == false ))
|
||
|
{
|
||
|
Mdl::Score *pScore = skater_obj->GetScoreObject();
|
||
|
|
||
|
// Check if a skater has just been eliminated in a firefight game
|
||
|
if( ( mod->GetGameMode()->GetNameChecksum() == CRCD(0xbff33600,"netfirefight" )) &&
|
||
|
( skater_obj->IsLocalClient() == false ))
|
||
|
{
|
||
|
// If this is the positive edge then hide the skater
|
||
|
if(( pScore->GetTotalScore() > 0 ) && ( score == 0 ))
|
||
|
{
|
||
|
Script::CStruct* params;
|
||
|
params = new Script::CStruct;
|
||
|
params->AddString( CRCD(0xa1dc81f9,"name"), skater_obj->GetDisplayName());
|
||
|
Script::RunScript( CRCD(0x9b043179,"announce_elimination"), params );
|
||
|
delete params;
|
||
|
mod->HideSkater( skater_obj, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pScore->SetTotalScore( score );
|
||
|
}
|
||
|
else if( skater_obj && !skater_obj->IsLocalClient())
|
||
|
{
|
||
|
Mdl::Score *pScore = skater_obj->GetScoreObject();
|
||
|
pScore->SetTotalScore( score );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( msg->m_Final )
|
||
|
{
|
||
|
gamenet_man->MarkReceivedFinalScores( true );
|
||
|
}
|
||
|
|
||
|
if( msg->m_Cheats != mod->GetCheatChecksum())
|
||
|
{
|
||
|
if( gamenet_man->HasCheatingOccurred() == false )
|
||
|
{
|
||
|
Script::RunScript( CRCD(0x1cedb62c,"notify_cheating"));
|
||
|
gamenet_man->CheatingOccured();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( mod->GetGameMode()->IsTeamGame())
|
||
|
{
|
||
|
int num_teams, score, highest_score, leading_team;
|
||
|
GameNet::PlayerInfo* my_player;
|
||
|
|
||
|
num_teams = mod->GetGameMode()->NumTeams();
|
||
|
leading_team = GameNet::vNO_TEAM;
|
||
|
highest_score = 0;
|
||
|
for( i = 0; i < num_teams; i++ )
|
||
|
{
|
||
|
score = gamenet_man->GetTeamScore( i );
|
||
|
if( score > highest_score )
|
||
|
{
|
||
|
highest_score = score;
|
||
|
leading_team = i;
|
||
|
}
|
||
|
else if( score == highest_score )
|
||
|
{
|
||
|
// A tie doesn't result in the panel message
|
||
|
leading_team = GameNet::vNO_TEAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( leading_team != GameNet::vNO_TEAM )
|
||
|
{
|
||
|
my_player = gamenet_man->GetLocalPlayer();
|
||
|
if( msg->m_Final )
|
||
|
{
|
||
|
if(( my_player->m_Skater ) && ( my_player->m_Team == leading_team ))
|
||
|
{
|
||
|
my_player->m_Skater->SelfEvent(CRCD(0x96935417,"WonGame"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( my_player->m_Skater )
|
||
|
{
|
||
|
my_player->m_Skater->SelfEvent(CRCD(0xe3ec7e9e,"LostGame"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( ( gamenet_man->GetCurrentLeadingTeam() != leading_team ) &&
|
||
|
( mod->GetGameMode()->IsTrue( "show_leader_messages" ) ) &&
|
||
|
( !gamenet_man->GameIsOver()))
|
||
|
|
||
|
{
|
||
|
// only print the message if you're competing against someone
|
||
|
if(( my_player->m_Skater ) && ( my_player->m_Team == leading_team ))
|
||
|
{
|
||
|
Script::RunScript( "NewScoreLeaderYourTeam", NULL, my_player->m_Skater );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char team_name[128];
|
||
|
|
||
|
sprintf( team_name, "team_%d_name", leading_team + 1 );
|
||
|
Script::CScriptStructure* pTempStructure = new Script::CScriptStructure;
|
||
|
pTempStructure->Clear();
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("String0"), ESYMBOLTYPE_STRING, Script::GetString( team_name ));
|
||
|
Script::RunScript( "NewScoreLeaderOtherTeam", pTempStructure, my_player->m_Skater );
|
||
|
delete pTempStructure;
|
||
|
}
|
||
|
gamenet_man->SetCurrentLeadingTeam( leading_team );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GameNet::PlayerInfo* player, *leader, *my_player;
|
||
|
Lst::Search< GameNet::PlayerInfo > sh;
|
||
|
int score, highest_score, num_players;
|
||
|
|
||
|
// Do the logic that figures out if there's a new winner and provides feedback
|
||
|
leader = NULL;
|
||
|
highest_score = 0;
|
||
|
num_players = 0;
|
||
|
for( player = gamenet_man->FirstPlayerInfo( sh ); player;
|
||
|
player = gamenet_man->NextPlayerInfo( sh ))
|
||
|
{
|
||
|
//if( player->IsLocalPlayer() && mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netgoalattack" ))
|
||
|
{
|
||
|
score = gamenet_man->GetPlayerScore( player->m_Skater->GetID());
|
||
|
}
|
||
|
//else
|
||
|
//{
|
||
|
//Mdl::Score *pScore = player->m_Skater->GetScoreObject();
|
||
|
|
||
|
//score = pScore->GetTotalScore();
|
||
|
//}
|
||
|
if( score > highest_score )
|
||
|
{
|
||
|
highest_score = score;
|
||
|
leader = player;
|
||
|
}
|
||
|
else if( score == highest_score )
|
||
|
{
|
||
|
// A tie doesn't result in the panel message
|
||
|
leader = NULL;
|
||
|
}
|
||
|
num_players++;
|
||
|
}
|
||
|
|
||
|
if( leader )
|
||
|
{
|
||
|
my_player = gamenet_man->GetLocalPlayer();
|
||
|
if( msg->m_Final )
|
||
|
{
|
||
|
if( leader->IsLocalPlayer())
|
||
|
{
|
||
|
leader->m_Skater->SelfEvent(CRCD(0x96935417,"WonGame"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( my_player->m_Skater )
|
||
|
{
|
||
|
leader->m_Skater->SelfEvent( CRCD(0xe3ec7e9e,"LostGame") );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( ( gamenet_man->GetCurrentLeader() != leader ) &&
|
||
|
( num_players > 1 ) &&
|
||
|
( mod->GetGameMode()->IsTrue( CRCD(0xd63dfd0f,"show_leader_messages") ) ) &&
|
||
|
( !front_end->GamePaused()))
|
||
|
|
||
|
{
|
||
|
// only print the message if you're competing against someone
|
||
|
if( leader->IsLocalPlayer())
|
||
|
{
|
||
|
Script::RunScript( CRCD(0xa1d334d0,"NewScoreLeaderYou"), NULL, leader->m_Skater );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Script::CScriptStructure* pTempStructure = new Script::CScriptStructure;
|
||
|
pTempStructure->Clear();
|
||
|
pTempStructure->AddComponent( CRCD(0xa4b08520,"String0"), ESYMBOLTYPE_STRING, leader->m_Name );
|
||
|
Script::RunScript( CRCD(0x7a4b9d14,"NewScoreLeaderOther"), pTempStructure, my_player->m_Skater );
|
||
|
delete pTempStructure;
|
||
|
}
|
||
|
gamenet_man->SetCurrentLeader( leader );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Start/Stop spark effect */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_sparks( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
GameNet::MsgObjMessage *msg;
|
||
|
Obj::CMovingObject *obj;
|
||
|
|
||
|
|
||
|
|
||
|
msg = (GameNet::MsgObjMessage *) context->m_Msg;
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
Obj::CSkater* skater_obj;
|
||
|
|
||
|
skater_obj = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater_obj != NULL,( "Got sparks message for non-CSkater\n" ));
|
||
|
|
||
|
if( skater_obj )
|
||
|
{
|
||
|
switch( context->m_MsgId )
|
||
|
{
|
||
|
case GameNet::MSG_ID_SPARKS_ON:
|
||
|
skater_obj->SparksOn();
|
||
|
break;
|
||
|
case GameNet::MSG_ID_SPARKS_OFF:
|
||
|
skater_obj->SparksOff();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Start/Stop blood effect */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_blood( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
Obj::CMovingObject *obj;
|
||
|
GameNet::MsgObjMessage* msg;
|
||
|
|
||
|
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
msg = (GameNet::MsgObjMessage* ) context->m_Msg;
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( msg->m_ObjId );
|
||
|
if( obj )
|
||
|
{
|
||
|
Obj::CSkater* skater_obj;
|
||
|
|
||
|
skater_obj = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater_obj != NULL,( "Got blood message for non-CSkater\n" ));
|
||
|
if( skater_obj )
|
||
|
{
|
||
|
switch( context->m_MsgId )
|
||
|
{
|
||
|
case GameNet::MSG_ID_BLOOD_ON:
|
||
|
{
|
||
|
GameNet::MsgBlood *msg;
|
||
|
|
||
|
msg = (GameNet::MsgBlood *) context->m_Msg;
|
||
|
// skater_obj->BloodOn( msg->m_BodyPart, msg->m_Size, msg->m_Frequency, msg->m_RandomRadius );
|
||
|
break;
|
||
|
}
|
||
|
case GameNet::MSG_ID_BLOOD_OFF:
|
||
|
{
|
||
|
GameNet::MsgBloodOff *msg;
|
||
|
|
||
|
msg = (GameNet::MsgBloodOff *) context->m_Msg;
|
||
|
// skater_obj->BloodOff( msg->m_BodyPart );
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Play a one-off sound given a position */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_play_sound( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::MsgPlaySound *msg;
|
||
|
Mth::Vector pos;
|
||
|
float vol, pitch, choice;
|
||
|
|
||
|
msg = (GameNet::MsgPlaySound *) context->m_Msg;
|
||
|
|
||
|
pos[X] = msg->m_Pos[0];
|
||
|
pos[Y] = msg->m_Pos[1];
|
||
|
pos[Z] = msg->m_Pos[2];
|
||
|
|
||
|
vol = (float) msg->m_VolPercent;
|
||
|
pitch = (float) msg->m_PitchPercent;
|
||
|
choice = (float) msg->m_SoundChoice;
|
||
|
|
||
|
Env::CTerrainManager::sPlaySound( (Env::ETerrainActionType) msg->m_WhichArray, (ETerrainType) msg->m_SurfaceFlag, pos, vol, pitch, choice, false );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Get all the game options */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_start_info( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Skate* skate_mod;
|
||
|
GameNet::MsgStartInfo* msg;
|
||
|
Script::CArray* mode_array;
|
||
|
int i;
|
||
|
|
||
|
Dbg_Printf( "********************************* Got lobby info\n" );
|
||
|
|
||
|
gamenet_man->SetJoinState( GameNet::vJOIN_STATE_CONNECTED );
|
||
|
gamenet_man->FreeServerList();
|
||
|
|
||
|
skate_mod = (Skate *) context->m_Data;
|
||
|
msg = (GameNet::MsgStartInfo*) context->m_Msg;
|
||
|
|
||
|
// Note whether or not the server is narrowband/broadband
|
||
|
if( msg->m_Broadband )
|
||
|
{
|
||
|
context->m_Conn->SetBandwidthType( Net::Conn::vBROADBAND );
|
||
|
context->m_Conn->SetSendInterval( Tmr::VBlanks( 2 ));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
context->m_Conn->SetBandwidthType( Net::Conn::vNARROWBAND );
|
||
|
context->m_Conn->SetSendInterval( Tmr::VBlanks( 2 ));
|
||
|
}
|
||
|
|
||
|
gamenet_man->SetNetworkGameId( msg->m_GameId );
|
||
|
gamenet_man->SetLevel( msg->m_LevelId );
|
||
|
gamenet_man->SetCrownSpawnPoint( msg->m_CrownSpawnPoint );
|
||
|
gamenet_man->SetSkaterStartingPoints( msg->m_StartPoints );
|
||
|
|
||
|
// set up the game mode for the client cause we're now in the lobby
|
||
|
// anything that's lobby-dependent should go after this line
|
||
|
Script::CScriptStructure* pTempStructure = new Script::CScriptStructure;
|
||
|
pTempStructure->Clear();
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("level"), ESYMBOLTYPE_NAME, (int)msg->m_LevelId );
|
||
|
Script::RunScript( "request_level", pTempStructure, NULL );
|
||
|
delete pTempStructure;
|
||
|
|
||
|
Script::RunScript( "leave_front_end" );
|
||
|
Script::RunScript( "cleanup_before_loading_level" );
|
||
|
|
||
|
context->m_Conn->UpdateCommTime(); // update the current comm time so it doesn't time out after
|
||
|
// laoding the level
|
||
|
|
||
|
skate_mod->GetGameMode()->SetMaximumNumberOfPlayers( msg->m_MaxPlayers );
|
||
|
skate_mod->GetGameMode()->LoadGameType( msg->m_GameMode );
|
||
|
//skate_mod->GetGameMode()->SetMaximumNumberOfPlayers( msg->m_MaxPlayers );
|
||
|
skate_mod->LaunchGame();
|
||
|
skate_mod->GetGameMode()->LoadGameType( msg->m_GameMode );
|
||
|
skate_mod->GetGameMode()->SetNumTeams( msg->m_TeamMode );
|
||
|
|
||
|
gamenet_man->SetProSetFlags( msg->m_ProSetFlags );
|
||
|
for( i = 0; i < GameNet::vMAX_NUM_PROSETS; i++ )
|
||
|
{
|
||
|
if(( 1 << i ) & msg->m_ProSetFlags )
|
||
|
{
|
||
|
Script::CStruct* pSetParams;
|
||
|
pSetParams = new Script::CStruct;
|
||
|
pSetParams->AddInteger( "flag", Script::GetInt( "FLAG_PROSET1_GEO_ON" ) + i );
|
||
|
Script::RunScript( "SetFlag", pSetParams );
|
||
|
delete pSetParams;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
Script::CScriptStructure* pTempStructure = new Script::CScriptStructure;
|
||
|
|
||
|
if( msg->m_GameMode != Script::GenerateCRC("netlobby" ))
|
||
|
{
|
||
|
// In king of the hill, interpret time limit as a target time
|
||
|
if( ( msg->m_TimeLimit == 0 ) &&
|
||
|
( msg->m_GameMode != Script::GenerateCRC( "netctf" )) &&
|
||
|
( msg->m_GameMode != Script::GenerateCRC( "netgoalattack" )))
|
||
|
{
|
||
|
if( ( msg->m_GameMode != CRCD(0x3d6d444f,"firefight")) &&
|
||
|
( msg->m_GameMode != CRCD(0xbff33600,"netfirefight")))
|
||
|
{
|
||
|
Script::CArray* pArray = new Script::CArray;
|
||
|
Script::CopyArray(pArray,Script::GetArray("targetScoreArray"));
|
||
|
|
||
|
Script::CScriptStructure* pSubStruct = pArray->GetStructure(0);
|
||
|
Dbg_Assert(pSubStruct);
|
||
|
pSubStruct->AddComponent(Script::GenerateCRC("score"),ESYMBOLTYPE_INTEGER, msg->m_TargetScore );
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("victory_conditions"), pArray );
|
||
|
}
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("default_time_limit"), ESYMBOLTYPE_INTEGER, (int) 0 );
|
||
|
skate_mod->SetTimeLimit( 0 );
|
||
|
skate_mod->GetGameMode()->OverrideOptions( pTempStructure );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("default_time_limit"), ESYMBOLTYPE_INTEGER, (int) msg->m_TimeLimit );
|
||
|
if( msg->m_GameMode == Script::GenerateCRC( "netctf" ))
|
||
|
{
|
||
|
Script::CArray* pArray = new Script::CArray;
|
||
|
Script::CopyArray(pArray,Script::GetArray("highestScoreArray") );
|
||
|
pTempStructure->AddComponent( Script::GenerateCRC("victory_conditions"), pArray );
|
||
|
}
|
||
|
skate_mod->SetTimeLimit( msg->m_TimeLimit );
|
||
|
skate_mod->GetGameMode()->SetTimeLeft( msg->m_TimeLeft );
|
||
|
skate_mod->GetGameMode()->OverrideOptions( pTempStructure );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete pTempStructure;
|
||
|
}
|
||
|
|
||
|
if( gamenet_man->InNetGame())
|
||
|
{
|
||
|
mode_array = Script::GetArray( "net_game_type_info" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mode_array = Script::GetArray( "mp_game_type_info" );
|
||
|
}
|
||
|
Dbg_Assert( mode_array );
|
||
|
|
||
|
for( i = 0; i < (int)mode_array->GetSize(); i++ )
|
||
|
{
|
||
|
uint32 value, script;
|
||
|
Script::CStruct* mode_struct;
|
||
|
|
||
|
mode_struct = mode_array->GetStructure( i );
|
||
|
Dbg_Assert( mode_struct );
|
||
|
|
||
|
mode_struct->GetChecksum( "checksum", &value, true );
|
||
|
if( value == msg->m_GameMode )
|
||
|
{
|
||
|
Script::CStruct* params;
|
||
|
|
||
|
params = new Script::CStruct;
|
||
|
params->AddInteger( "time", msg->m_TimeLimit );
|
||
|
params->AddInteger( "score", msg->m_TargetScore );
|
||
|
if( msg->m_TimeLimit == 0 )
|
||
|
{
|
||
|
params->AddInteger( CRCD(0xf0e712d2,"unlimited_time"), 1 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
params->AddInteger( CRCD(0xf0e712d2,"unlimited_time"), 0 );
|
||
|
}
|
||
|
//Dbg_Printf( "Target Score : %d\n", msg->m_TargetScore );
|
||
|
mode_struct->GetChecksum( "goal_script", &script, true );
|
||
|
Script::RunScript( script, params );
|
||
|
delete params;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( ( gamenet_man->InNetGame()) &&
|
||
|
( gamenet_man->GetJoinMode() == GameNet::vJOIN_MODE_PLAY ))
|
||
|
{
|
||
|
if( !CFuncs::ScriptIsObserving( NULL, NULL ))
|
||
|
{
|
||
|
gamenet_man->SendFaceDataToServer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Parse the object update stream from the server and update the */
|
||
|
/* appropriate objects */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int Skate::handle_object_update_relay( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Skate* mod;
|
||
|
int update_flags;
|
||
|
unsigned char obj_id, obj_id_mask;
|
||
|
Net::BitStream stream;
|
||
|
|
||
|
Dbg_Assert( context );
|
||
|
|
||
|
mod = (Skate *) context->m_Data;
|
||
|
stream.SetInputData( context->m_Msg, 1024 );
|
||
|
obj_id_mask = stream.ReadUnsignedValue( sizeof( char ) * 8 );
|
||
|
|
||
|
for( obj_id = 0; obj_id < vMAX_SKATERS; obj_id++ )
|
||
|
{
|
||
|
GameNet::ObjectUpdate obj_update;
|
||
|
Obj::CMovingObject* obj;
|
||
|
Mth::Vector eulers;
|
||
|
short pos[3];
|
||
|
short fixed;
|
||
|
char doing_trick, state, terrain, walking, driving;
|
||
|
Flags< int > skater_flags;
|
||
|
Flags< int > end_run_flags;
|
||
|
sint16 rail_node;
|
||
|
int i;
|
||
|
unsigned short timestamp;
|
||
|
|
||
|
// If the bit for this player number is not set, that means there is no
|
||
|
// object update for them. Continue
|
||
|
if(( obj_id_mask & ( 1 << obj_id )) == 0 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//Dbg_Printf( "================ Got update for player %d\n", obj_id );
|
||
|
|
||
|
timestamp = stream.ReadUnsignedValue( sizeof( uint16 ) * 8 );
|
||
|
update_flags = stream.ReadUnsignedValue( 9 );
|
||
|
|
||
|
//Dbg_Printf( "Got Object Update For %d, Time: %d Mask %d\n", obj_id, timestamp, obj_id_mask );
|
||
|
|
||
|
doing_trick = 0;
|
||
|
state = 0;
|
||
|
skater_flags = 0;
|
||
|
end_run_flags = 0;
|
||
|
terrain = 0;
|
||
|
walking = 0;
|
||
|
driving = 0;
|
||
|
rail_node = -1;
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_X )
|
||
|
{
|
||
|
pos[X] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[X] = stream.ReadFloatValue();
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Y )
|
||
|
{
|
||
|
pos[Y] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[Y] = stream.ReadFloatValue();
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_POS_Z )
|
||
|
{
|
||
|
pos[Z] = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
//pos[Z] = stream.ReadFloatValue();
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_X )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[X] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Y )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[Y] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_ROT_Z )
|
||
|
{
|
||
|
fixed = stream.ReadSignedValue( sizeof( short ) * 8 );
|
||
|
eulers[Z] = ((float) fixed ) / 4096.0f;
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_STATE )
|
||
|
{
|
||
|
char mask;
|
||
|
|
||
|
mask = stream.ReadUnsignedValue( 4 );
|
||
|
|
||
|
state = mask & GameNet::mSTATE_MASK;
|
||
|
doing_trick = (( mask & GameNet::mDOING_TRICK_MASK ) != 0 );
|
||
|
terrain = stream.ReadUnsignedValue( 6 );
|
||
|
walking = stream.ReadUnsignedValue( 1 );
|
||
|
driving = stream.ReadUnsignedValue( 1 );
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_FLAGS )
|
||
|
{
|
||
|
skater_flags = stream.ReadUnsignedValue( 5 );
|
||
|
end_run_flags = stream.ReadUnsignedValue( 3 );
|
||
|
}
|
||
|
|
||
|
if( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE )
|
||
|
{
|
||
|
rail_node = stream.ReadSignedValue( sizeof( sint16 ) * 8 );
|
||
|
//Dbg_Printf( "Got rail node %d\n", rail_node );
|
||
|
}
|
||
|
|
||
|
obj = (Obj::CMovingObject *) mod->GetObjectManager()->GetObjectByID( obj_id );
|
||
|
|
||
|
// Make sure that we actually have this object in our list of objects
|
||
|
// Also, reject late/foreign object update messages. We still needed to do all the stream
|
||
|
// parsing though because we need to return the length of the message to the dispatcher
|
||
|
if( ( obj != NULL ) &&
|
||
|
(( context->m_PacketFlags & ( Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN )) == 0 ))
|
||
|
{
|
||
|
Obj::CSkater* skater_obj;
|
||
|
|
||
|
skater_obj = static_cast< Obj::CSkater *> ( obj );
|
||
|
Dbg_MsgAssert( skater_obj != NULL,( "Got object update for non-CSkater\n" ));
|
||
|
|
||
|
if( skater_obj )
|
||
|
{
|
||
|
Obj::SPosEvent* p_pos_history = skater_obj->GetStateHistory()->GetPosHistory();
|
||
|
|
||
|
int index, last_index;
|
||
|
|
||
|
if( skater_obj->GetStateHistory()->GetNumPosUpdates() > 0 )
|
||
|
{
|
||
|
last_index = ( skater_obj->GetStateHistory()->GetNumPosUpdates() - 1 ) % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Mth::Matrix obj_matrix;
|
||
|
Mth::Vector eulers;
|
||
|
last_index = 0;
|
||
|
|
||
|
obj_matrix = skater_obj->GetMatrix();
|
||
|
obj_matrix.GetEulers( eulers );
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
if( i == Y )
|
||
|
{
|
||
|
p_pos_history[0].ShortPos[i] = (short) ( skater_obj->m_pos[i] * 4.0f );
|
||
|
//p_pos_history[0].ShortPos[i] = skater_obj->m_pos[i];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
p_pos_history[0].ShortPos[i] = (short) ( skater_obj->m_pos[i] * 2.0f );
|
||
|
//p_pos_history[0].ShortPos[i] = skater_obj->m_pos[i];
|
||
|
}
|
||
|
p_pos_history[0].Eulers[i] = eulers[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
index = skater_obj->GetStateHistory()->GetNumPosUpdates() % Obj::CSkaterStateHistoryComponent::vNUM_POS_HISTORY_ELEMENTS;
|
||
|
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_POS_X ))
|
||
|
{
|
||
|
pos[X] = p_pos_history[last_index].ShortPos[X];
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_POS_Y ))
|
||
|
{
|
||
|
pos[Y] = p_pos_history[last_index].ShortPos[Y];
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_POS_Z ))
|
||
|
{
|
||
|
pos[Z] = p_pos_history[last_index].ShortPos[Z];
|
||
|
}
|
||
|
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
p_pos_history[index].ShortPos[i] = pos[i];
|
||
|
}
|
||
|
|
||
|
obj_update.m_Pos.Set( ((float) pos[X] ) / 2.0f,//pos[X],
|
||
|
((float) pos[Y] ) / 4.0f,//pos[Y],
|
||
|
((float) pos[Z] ) / 2.0f,//pos[Z],
|
||
|
0.0f );
|
||
|
//Dbg_Printf( "*** Got Pos[%.2f %.2f %.2f]\n", obj_update.m_Pos[X], obj_update.m_Pos[Y], obj_update.m_Pos[Z] );
|
||
|
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_ROT_X ))
|
||
|
{
|
||
|
eulers[X] = p_pos_history[last_index].Eulers[X];
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_ROT_Y ))
|
||
|
{
|
||
|
eulers[Y] = p_pos_history[last_index].Eulers[Y];
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_ROT_Z ))
|
||
|
{
|
||
|
eulers[Z] = p_pos_history[last_index].Eulers[Z];
|
||
|
}
|
||
|
|
||
|
// Update history
|
||
|
for( i = 0; i < 3; i++ )
|
||
|
{
|
||
|
p_pos_history[index].Eulers[i] = eulers[i];
|
||
|
}
|
||
|
|
||
|
// Use those euler angles to compose a matrix
|
||
|
Mth::Matrix obj_matrix( eulers[X], eulers[Y], eulers[Z] );
|
||
|
obj_update.m_Matrix = obj_matrix;
|
||
|
|
||
|
p_pos_history[index].Matrix = obj_update.m_Matrix;
|
||
|
p_pos_history[index].Position = obj_update.m_Pos;
|
||
|
|
||
|
Mth::Vector vel;
|
||
|
vel = p_pos_history[index].Position - p_pos_history[last_index].Position;
|
||
|
//Dbg_Printf( "(%d) Vel: %f %f %f\n", timestamp, vel[X], vel[Y], vel[Z] );
|
||
|
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_STATE ))
|
||
|
{
|
||
|
state = p_pos_history[last_index].State;
|
||
|
doing_trick = p_pos_history[last_index].DoingTrick;
|
||
|
terrain = p_pos_history[last_index].Terrain;
|
||
|
walking = p_pos_history[last_index].Walking;
|
||
|
driving = p_pos_history[last_index].Driving;
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_FLAGS ))
|
||
|
{
|
||
|
skater_flags = p_pos_history[last_index].SkaterFlags;
|
||
|
end_run_flags = p_pos_history[last_index].EndRunFlags;
|
||
|
}
|
||
|
if( !( update_flags & GameNet::mUPDATE_FIELD_RAIL_NODE ))
|
||
|
{
|
||
|
rail_node = p_pos_history[last_index].RailNode;
|
||
|
}
|
||
|
|
||
|
p_pos_history[index].SkaterFlags = skater_flags;
|
||
|
p_pos_history[index].EndRunFlags = end_run_flags;
|
||
|
p_pos_history[index].RailNode = rail_node;
|
||
|
p_pos_history[index].State = state;
|
||
|
p_pos_history[index].DoingTrick = doing_trick;
|
||
|
p_pos_history[index].Terrain = (ETerrainType) terrain;
|
||
|
p_pos_history[index].Walking = walking;
|
||
|
p_pos_history[index].Driving = driving;
|
||
|
|
||
|
// Update the lo and hi words of the timestamp
|
||
|
p_pos_history[index].HiTime = p_pos_history[last_index].HiTime;
|
||
|
|
||
|
// If the lo-word has flipped, increment the hi-word
|
||
|
if( p_pos_history[last_index].LoTime > timestamp )
|
||
|
{
|
||
|
p_pos_history[index].HiTime++;
|
||
|
}
|
||
|
p_pos_history[index].LoTime = timestamp;
|
||
|
//Dbg_Printf( "(%d) Got time: %d\n", context->m_App->m_FrameCounter, p_pos_history[index].GetTime());
|
||
|
|
||
|
|
||
|
skater_obj->GetStateHistory()->IncrementNumPosUpdates();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::StartServer( void )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
|
||
|
Net::Server* server;
|
||
|
bool net_game;
|
||
|
|
||
|
net_game = false;
|
||
|
// prevents fragmentation
|
||
|
//CFuncs::ScriptCleanup( NULL, NULL );
|
||
|
if( gamenet_man->InNetMode())
|
||
|
{
|
||
|
net_game = true;
|
||
|
gamenet_man->ClientShutdown();
|
||
|
}
|
||
|
|
||
|
server = gamenet_man->SpawnServer( !net_game, true );
|
||
|
if( server == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
mlp_manager->AddLogicTask ( *m_object_update_task );
|
||
|
mlp_manager->AddLogicTask ( *m_score_update_task );
|
||
|
|
||
|
// These handlers remaio active throughout the server's life
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE, handle_score_request );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_LANDED_TRICK, handle_landed_trick, 0, this );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_COMBO_REPORT, handle_combo_report, 0, this );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHAT, handle_msg_relay, Net::mHANDLE_LATE );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_BAIL_DONE, handle_bail_done, Net::mHANDLE_LATE );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBJ_UPDATE_STREAM, handle_object_update,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN );
|
||
|
|
||
|
// In Split Screen Games, Don't relay any messages
|
||
|
if( !server->IsLocal())
|
||
|
{
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_FACE_DATA, handle_face_data );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_PROJECTILE, handle_msg_relay, 0, this );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_enter_vehicle_server );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_PRIM_ANIM_START, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_TARGET, handle_selective_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_SKATEBOARD, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_DISPLAY, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_CREATE_SPECIAL_ITEM, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_DESTROY_SPECIAL_ITEM, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_DETAILS, handle_selective_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_LOOPING_TYPE, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_HIDE_ATOMIC, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_ANIM_SPEED, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_SOUND, handle_selective_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_LOOPING_SOUND, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_ON, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_OFF, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_ON, handle_msg_relay );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_OFF, handle_msg_relay, Net::mHANDLE_LATE );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_RUN_SCRIPT, handle_script_relay, Net::mHANDLE_LATE );
|
||
|
server->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT, handle_script_relay, Net::mHANDLE_LATE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::LaunchNetworkGame( void )
|
||
|
{
|
||
|
RestartLevel();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::AddNetworkMsgHandlers( Net::Client* client, int index )
|
||
|
{
|
||
|
Obj::CSkater* skater;
|
||
|
|
||
|
Dbg_Assert( client );
|
||
|
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_START_INFO, handle_start_info, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBJ_UPDATE_STREAM, handle_object_update_relay,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_PRIM_ANIM_START, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_TOGGLE_CHEAT, handle_cheats, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_TARGET, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_DISPLAY, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_CLEAR_ROTATE_DISPLAY, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_CREATE_SPECIAL_ITEM, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_DESTROY_SPECIAL_ITEM, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_ROTATE_SKATEBOARD, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_anims, 0, this, Net::HIGHEST_PRIORITY );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_FLIP_ANIM, handle_flip_anim, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_WOBBLE_DETAILS, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_LOOPING_TYPE, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_HIDE_ATOMIC, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SET_ANIM_SPEED, handle_anims, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAYER_QUIT, handle_player_quit,
|
||
|
Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_HOST_QUIT, handle_disconn_accepted,
|
||
|
Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_SOUND, handle_play_sound, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_PLAY_LOOPING_SOUND, handle_play_sound, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_ON, handle_sparks, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPARKS_OFF, handle_sparks, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_ON, handle_blood, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_BLOOD_OFF, handle_blood, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE_UPDATE, handle_score_update,
|
||
|
Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHANGE_LEVEL, handle_change_level, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_RUN_SCRIPT, handle_run_script, Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_AND_RUN_SCRIPT, handle_spawn_run_script, Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_KICKED, handle_kicked, Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_LEFT_OUT, handle_kicked, Net::mHANDLE_LATE, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBSERVER_LOG_TRICK_OBJ, handle_obs_log_trick_objects, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_OBSERVER_INIT_GRAFFITI_STATE, handle_obs_init_graffiti_state, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_FACE_DATA, handle_face_data, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_CHEAT_LIST, handle_cheat_list, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SPAWN_PROJECTILE, handle_projectile, 0, this );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_ENTER_VEHICLE, handle_enter_vehicle_client, 0, this );
|
||
|
|
||
|
for( uint i = 0; i < vMAX_SKATERS; i++ )
|
||
|
{
|
||
|
skater = GetSkater( i );
|
||
|
if( skater && skater->IsLocalClient() && ( skater->GetHeapIndex() == index ))
|
||
|
{
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SCORE, Mdl::Score::s_handle_score_message, 0, skater );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_WON, Obj::CSkaterStateHistoryComponent::sHandleCollision, 0, skater );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_COLLIDE_LOST, Obj::CSkaterStateHistoryComponent::sHandleCollision, 0, skater );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_PROJECTILE_HIT_TARGET, Obj::CSkaterStateHistoryComponent::sHandleProjectileHit, 0, skater );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_SKATER_HIT_BY_PROJECTILE, Obj::CSkaterStateHistoryComponent::sHandleProjectileHit, 0, skater );
|
||
|
client->m_Dispatcher.AddHandler( GameNet::MSG_ID_STEAL_MESSAGE, Obj::CSkaterLocalNetLogicComponent::sHandleStealMessage, 0, skater );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::LeaveServer( void )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
Net::Client* client;
|
||
|
|
||
|
|
||
|
|
||
|
if( gamenet_man->OnServer())
|
||
|
{
|
||
|
Net::App* server;
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
server = gamenet_man->GetServer();
|
||
|
Dbg_Assert( server );
|
||
|
|
||
|
// If we were auto serving, shut that service down
|
||
|
if( gamenet_man->GetHostMode() == GameNet::vHOST_MODE_AUTO_SERVE )
|
||
|
{
|
||
|
gamenet_man->AutoServerShutdown();
|
||
|
}
|
||
|
|
||
|
// First, wait for any pending network tasks to finish before sending out final disconn
|
||
|
// message
|
||
|
#ifdef __PLAT_NGPS__
|
||
|
//server->WaitForAsyncCallsToFinish();
|
||
|
#endif
|
||
|
|
||
|
// Send off last message, notifying clients that I'm about to quit
|
||
|
Dbg_Printf( "Starting server shutdown\n" );
|
||
|
msg_desc.m_Id = GameNet::MSG_ID_HOST_QUIT;
|
||
|
msg_desc.m_Priority = Net::HIGHEST_PRIORITY;
|
||
|
server->EnqueueMessage( Net::HANDLE_ID_BROADCAST, &msg_desc );
|
||
|
// Wake the network thread up to send the data
|
||
|
server->SendData();
|
||
|
|
||
|
// Wait for that final send to complete
|
||
|
#ifdef __PLAT_NGPS__
|
||
|
//server->WaitForAsyncCallsToFinish();
|
||
|
#endif
|
||
|
gamenet_man->ServerShutdown();
|
||
|
|
||
|
m_object_update_task->Remove();
|
||
|
m_score_update_task->Remove();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
client = gamenet_man->GetClient( 0 );
|
||
|
if( client )
|
||
|
{
|
||
|
Net::MsgDesc msg_desc;
|
||
|
// First, wait for any pending network tasks to finish before sending out final disconn
|
||
|
// message
|
||
|
#ifdef __PLAT_NGPS__
|
||
|
//client->WaitForAsyncCallsToFinish();
|
||
|
#endif
|
||
|
Dbg_Printf( "Leaving server\n" );
|
||
|
|
||
|
msg_desc.m_Id = Net::MSG_ID_DISCONN_REQ;
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
// Send off last message, notifying server that I'm about to quit
|
||
|
client->EnqueueMessageToServer( &msg_desc );
|
||
|
// Wake the network thread up to send the data
|
||
|
client->SendData();
|
||
|
|
||
|
// Wait for that final send to complete
|
||
|
#ifdef __PLAT_NGPS__
|
||
|
//client->WaitForAsyncCallsToFinish();
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gamenet_man->DisconnectFromServer();
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::SetLaunchingQueuedScripts( void )
|
||
|
{
|
||
|
m_launching_queued_scripts = true;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::ClearLaunchingQueuedScripts( void )
|
||
|
{
|
||
|
m_launching_queued_scripts = false;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
bool Skate::LaunchingQueuedScripts( void )
|
||
|
{
|
||
|
return m_launching_queued_scripts;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void Skate::SendCheatList( GameNet::PlayerInfo* player )
|
||
|
{
|
||
|
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
|
||
|
GameNet::MsgEnabledCheats cheat_msg;
|
||
|
Net::MsgDesc msg_desc;
|
||
|
|
||
|
cheat_msg.m_NumCheats = 0;
|
||
|
|
||
|
if( mp_career->GetCheat( CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xb38341c9, "CHEAT_PERFECT_MANUAL")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xb38341c9, "CHEAT_PERFECT_MANUAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xcd09e062, "CHEAT_PERFECT_RAIL")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xcd09e062, "CHEAT_PERFECT_RAIL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x69a1ce96, "CHEAT_PERFECT_SKITCH")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x69a1ce96, "CHEAT_PERFECT_SKITCH");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x6b0f24bc, "CHEAT_STATS_13")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x6b0f24bc, "CHEAT_STATS_13");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x520a66ef,"FLAG_G_EXPERT_MODE_NO_REVERTS")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0x520a66ef,"FLAG_G_EXPERT_MODE_NO_REVERTS");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xeba89179,"FLAG_G_EXPERT_MODE_NO_WALKING")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xeba89179,"FLAG_G_EXPERT_MODE_NO_WALKING");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xc4ffc672,"FLAG_G_EXPERT_MODE_NO_MANUALS")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xc4ffc672,"FLAG_G_EXPERT_MODE_NO_MANUALS");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xd5982173,"NO_G_DISPLAY_BALANCE")))
|
||
|
{
|
||
|
cheat_msg.m_Cheats[cheat_msg.m_NumCheats++] = CRCD(0xd5982173,"NO_G_DISPLAY_BALANCE");
|
||
|
}
|
||
|
|
||
|
// Send it, even if there are zero cheats. This triggers the clearing of all cheats on
|
||
|
// the client side
|
||
|
msg_desc.m_Id = GameNet::MSG_ID_CHEAT_LIST;
|
||
|
msg_desc.m_Data = &cheat_msg;
|
||
|
msg_desc.m_Length = sizeof( int ) +( sizeof( uint32 ) * cheat_msg.m_NumCheats );
|
||
|
|
||
|
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
|
||
|
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
|
||
|
|
||
|
gamenet_man->GetServer()->EnqueueMessage( player->GetConnHandle(), &msg_desc );
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
uint32 Skate::GetCheatChecksum( void )
|
||
|
{
|
||
|
uint32 checksum;
|
||
|
|
||
|
checksum = 0;
|
||
|
|
||
|
if( mp_career->GetCheat( CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL")))
|
||
|
{
|
||
|
checksum |= CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xb38341c9, "CHEAT_PERFECT_MANUAL")))
|
||
|
{
|
||
|
checksum |= CRCD(0xb38341c9, "CHEAT_PERFECT_MANUAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xcd09e062, "CHEAT_PERFECT_RAIL")))
|
||
|
{
|
||
|
checksum |= CRCD(0xcd09e062, "CHEAT_PERFECT_RAIL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x69a1ce96, "CHEAT_PERFECT_SKITCH")))
|
||
|
{
|
||
|
checksum |= CRCD(0x69a1ce96, "CHEAT_PERFECT_SKITCH");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL")))
|
||
|
{
|
||
|
checksum |= CRCD(0xeefecf1b, "CHEAT_ALWAYS_SPECIAL");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x6b0f24bc, "CHEAT_STATS_13")))
|
||
|
{
|
||
|
checksum |= CRCD(0x6b0f24bc, "CHEAT_STATS_13");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0x520a66ef,"FLAG_G_EXPERT_MODE_NO_REVERTS")))
|
||
|
{
|
||
|
checksum |= CRCD(0x520a66ef,"FLAG_G_EXPERT_MODE_NO_REVERTS");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xeba89179,"FLAG_G_EXPERT_MODE_NO_WALKING")))
|
||
|
{
|
||
|
checksum |= CRCD(0xeba89179,"FLAG_G_EXPERT_MODE_NO_WALKING");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xc4ffc672,"FLAG_G_EXPERT_MODE_NO_MANUALS")))
|
||
|
{
|
||
|
checksum |= CRCD(0xc4ffc672,"FLAG_G_EXPERT_MODE_NO_MANUALS");
|
||
|
}
|
||
|
if( mp_career->GetCheat( CRCD(0xd5982173,"NO_G_DISPLAY_BALANCE")))
|
||
|
{
|
||
|
checksum |= CRCD(0xd5982173,"NO_G_DISPLAY_BALANCE");
|
||
|
}
|
||
|
|
||
|
return checksum;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
} // namespace Mdl
|