1
0
forked from 0ad/0ad

- Added pause game functionality.

- Removed CDamageType from the engine - damage is now handled only
within the entity script (easier to mod/modify).

This was SVN commit r3325.
This commit is contained in:
Matei 2006-01-02 03:07:29 +00:00
parent b045cfd480
commit 0a3e9ec537
19 changed files with 115 additions and 67 deletions

View File

@ -109,6 +109,7 @@ sound.mastergain = 0.5
; > SYSTEM SETTINGS
hotkey.exit = Escape, "Ctrl+F4" ; Exit to desktop.
hotkey.pause = Pause ; Pause/unpause game.
hotkey.screenshot = F2 ; Take PNG screenshot.
hotkey.bigscreenshot = "Ctrl+Alt+F2" ; Take large BMP screenshot.
hotkey.screenshot.watermark = "W" ; Toggle product/company watermark for official screenshots.

View File

@ -16,12 +16,8 @@
</Creation>
</Traits>
<Script File="entities/template_entity_script.js" />
<Event On="Attack" Function="entityEventAttack" />
<Event On="Gather" Function="entityEventGather" />
<Event On="Heal" Function="entityEventHeal" />
<Script File="entities/template_entity_script.js" />
<Event On="Generic" Function="entityEventGeneric" />
<Event On="TakesDamage" Function="entityEventTakesDamage" />
<Event On="TargetChanged" Function="entityEventTargetChanged" />
</Entity>

View File

@ -126,10 +126,14 @@ function entityInit()
}
}
// Attach functions to ourselves
this.processAttack = entityEventAttack;
this.processAttackRanged = entityEventAttackRanged;
this.processGather = entityEventGather;
this.processHeal = entityEventHeal;
this.damage = entityDamage;
// Attach Auras if the entity is entitled to them.
if( this.traits.auras )
@ -262,14 +266,14 @@ function entityEventAttackRanged( evt )
evt.stopPropagation();
console.write( "Fire!" );
//console.write( "Fire!" );
}
// ====================================================================
function projectileEventImpact( evt )
{
console.write( "Hit!" );
//console.write( "Hit!" );
evt.impacted.damage( this.damage, evt.originator );
// Just so you know - there's no guarantee that evt.impacted is the thing you were
@ -385,17 +389,17 @@ function entityEventHeal( evt )
// ====================================================================
function entityEventTakesDamage( evt )
{
function entityDamage( damage, inflictor )
{
// Apply armour and work out how much damage we actually take
crushDamage = parseInt(evt.damage.crush - this.traits.armour.value * this.traits.armour.crush);
crushDamage = parseInt(damage.crush - this.traits.armour.value * this.traits.armour.crush);
if ( crushDamage < 0 ) crushDamage = 0;
pierceDamage = parseInt(evt.damage.pierce - this.traits.armour.value * this.traits.armour.pierce);
pierceDamage = parseInt(damage.pierce - this.traits.armour.value * this.traits.armour.pierce);
if ( pierceDamage < 0 ) pierceDamage = 0;
hackDamage = parseInt(evt.damage.hack - this.traits.armour.value * this.traits.armour.hack);
hackDamage = parseInt(damage.hack - this.traits.armour.value * this.traits.armour.hack);
if ( hackDamage < 0 ) hackDamage = 0;
totalDamage = parseInt(evt.damage.typeless + crushDamage + pierceDamage + hackDamage);
totalDamage = parseInt(damage.typeless + crushDamage + pierceDamage + hackDamage);
// Minimum of 1 damage
@ -406,13 +410,13 @@ function entityEventTakesDamage( evt )
if( this.traits.health.curr <= 0 )
{
// If the inflictor gains promotions, and he's capable of earning more ranks,
if (evt.inflictor.traits.up && evt.inflictor.traits.up.curr && evt.inflictor.traits.up.req
&& evt.inflictor.traits.up.newentity && evt.inflictor.traits.up.newentity != ""
if (inflictor.traits.up && inflictor.traits.up.curr && inflictor.traits.up.req
&& inflictor.traits.up.newentity && inflictor.traits.up.newentity != ""
&& this.traits.loot && this.traits.loot.up)
{
// Give him the fallen's upgrade points (if he has any).
if (this.traits.loot.up)
evt.inflictor.traits.up.curr = parseInt(evt.inflictor.traits.up.curr) + parseInt(this.traits.loot.up);
inflictor.traits.up.curr = parseInt(inflictor.traits.up.curr) + parseInt(this.traits.loot.up);
// Notify player.
if (this.traits.id.specific)
@ -421,7 +425,7 @@ function entityEventTakesDamage( evt )
console.write("One of your units has earned " + this.traits.loot.up + " upgrade points!");
// If he now has maximum upgrade points for his rank,
if (evt.inflictor.traits.up.curr >= evt.inflictor.traits.up.req)
if (inflictor.traits.up.curr >= inflictor.traits.up.req)
{
// Notify the player.
if (this.traits.id.specific)
@ -430,13 +434,13 @@ function entityEventTakesDamage( evt )
console.write("One of your units has gained a promotion!");
// Reset his upgrade points.
evt.inflictor.traits.up.curr = 0;
inflictor.traits.up.curr = 0;
// Upgrade his portrait to the next level.
evt.inflictor.traits.id.icon_cell++;
inflictor.traits.id.icon_cell++;
// Transmogrify him into his next rank.
evt.inflictor.template = getEntityTemplate(evt.inflictor.traits.up.newentity);
inflictor.template = getEntityTemplate(inflictor.traits.up.newentity);
}
}
@ -462,8 +466,8 @@ function entityEventTakesDamage( evt )
}
// Notify player.
if( evt.inflictor )
console.write( this.traits.id.generic + " got the point of " + evt.inflictor.traits.id.generic + "'s weapon." );
if( inflictor )
console.write( this.traits.id.generic + " got the point of " + inflictor.traits.id.generic + "'s weapon." );
else
console.write( this.traits.id.generic + " died in mysterious circumstances." );
@ -482,13 +486,13 @@ function entityEventTakesDamage( evt )
console.write("Kill!!");
this.kill();
}
else if( evt.inflictor && this.actions.attack )
else if( inflictor && this.actions.attack )
{
// If we're not already doing something else, take a measured response - hit 'em back.
// You know, I think this is quite possibly the first AI code the AI divlead has written
// for 0 A.D....
if( this.isIdle() )
this.order( ORDER_ATTACK, evt.inflictor );
this.order( ORDER_GENERIC, inflictor, ACTION_ATTACK );
}
}
@ -799,7 +803,17 @@ function canGather( source, target )
// ====================================================================
function DamageModifyAura ( source, ally, bonus )
function DamageType()
{
this.typeless = 0.0;
this.crush = 0.0;
this.pierce = 0.0;
this.hack = 0.0;
}
// ====================================================================
function DamageModifyAura( source, ally, bonus )
{
// Defines the effects of the DamageModify Aura. (Adjacent units have modified attack bonus.)
// The Courage Aura uses this function to give attack bonus to allies.
@ -842,7 +856,7 @@ function DamageModifyAura ( source, ally, bonus )
// ====================================================================
function DropsiteAura ( source, types )
function DropsiteAura( source, types )
{
// Defines the effects of the Gather aura. Enables resource gathering on entities
// near the source for it's owner.
@ -876,7 +890,7 @@ function DropsiteAura ( source, types )
// ====================================================================
function InfidelityAura ( source, time )
function InfidelityAura( source, time )
{
// Defines the effects of the Infidelity Aura. Changes ownership of entity when only one player's units surrounds them.

View File

@ -23,8 +23,8 @@
</Audio>
<Footprint>
<Radius>.5</Radius>
<Height>1.5</Height>
<Radius>0.5</Radius>
<Height>4.0</Height>
</Footprint>
<Health>

View File

@ -41,7 +41,7 @@
hotkey="water.raise"
>
<action on="Press"><![CDATA[
setWaterHeight(getWaterHeight() + 0.25);
setWaterHeight( getWaterHeight() + 0.25 );
]]></action>
</object>
@ -50,7 +50,16 @@
hotkey="water.lower"
>
<action on="Press"><![CDATA[
setWaterHeight(getWaterHeight() - 0.25);
setWaterHeight( getWaterHeight() - 0.25 );
]]></action>
</object>
<!-- EMPTY OBJECT USED TO PAUSE/UNPAUSE GAME. -->
<object name="snPause"
hotkey="pause"
>
<action on="Press"><![CDATA[
setPaused( !isPaused() );
]]></action>
</object>

View File

@ -148,7 +148,7 @@ static void Frame()
// decide if update/render is necessary
bool need_render, need_update;
if(g_app_minimized)
if( g_app_minimized )
{
// TODO: eventually update ought to be re-enabled so the server host
// can Alt+Tab out without the match hanging. however, game updates
@ -160,15 +160,14 @@ static void Frame()
// don't use SDL_WaitEvent: don't want the main loop to freeze until app focus is restored
SDL_Delay(10);
}
else if(!g_app_has_focus)
else if( !g_app_has_focus )
{
need_update = false; // see above
need_render = true;
SDL_Delay(5); // see above
}
// active
else
else // active
{
need_update = true;
need_render = true;

View File

@ -32,7 +32,8 @@ CGame::CGame():
m_Simulation(this),
m_GameView(this),
m_pLocalPlayer(NULL),
m_GameStarted(false)
m_GameStarted(false),
m_Paused(false)
{
debug_printf("CGame::CGame(): Game object CREATED; initializing..\n");
}
@ -125,6 +126,11 @@ PSRETURN CGame::StartGame(CGameAttributes *pAttribs)
void CGame::Update(double deltaTime)
{
if( m_Paused )
{
return;
}
m_Simulation.Update(deltaTime);
// TODO Detect game over and bring up the summary screen or something

View File

@ -44,6 +44,8 @@ public:
CGame();
~CGame();
bool m_Paused;
/*
Initialize all local state and members for playing a game described by
the attribute class, and start the game.

View File

@ -479,7 +479,7 @@ static void InitScripting()
CPlayer::ScriptingInit();
PlayerCollection::Init( "PlayerCollection" );
CDamageType::ScriptingInit();
//CDamageType::ScriptingInit();
CJSComplexPropertyAccessor<CEntity>::ScriptingInit(); // <-- Doesn't really matter which we use, but we know CJSPropertyAccessor<T> is already being compiled for T = CEntity.
CScriptEvent::ScriptingInit();
CJSProgressTimer::ScriptingInit();

View File

@ -135,7 +135,8 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_PLAYMUSIC, "playmusic", SDLK_p, 0 },
{ HOTKEY_WATER_TOGGLE, "water.toggle", SDLK_q, 0 },
{ HOTKEY_WATER_RAISE, "water.toggle", SDLK_a, 0 },
{ HOTKEY_WATER_LOWER, "water.toggle", SDLK_z, 0 }
{ HOTKEY_WATER_LOWER, "water.toggle", SDLK_z, 0 },
{ HOTKEY_PAUSE, "pause", SDLK_PAUSE, 0 }
};
/* SDL-type ends */

View File

@ -99,8 +99,8 @@ enum
HOTKEY_WATER_TOGGLE,
HOTKEY_WATER_RAISE,
HOTKEY_WATER_LOWER,
HOTKEY_PAUSE,
HOTKEY_LAST,
HOTKEY_NEGATION_FLAG = 65536

View File

@ -913,6 +913,29 @@ JSBool setWaterAlphaOffset( JSContext* cx, JSObject* UNUSED(globalObject), uint
return( JS_TRUE );
}
// Is the game paused?
JSBool isPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_NO_PARAMS( isPaused );
*rval = g_Game->m_Paused ? JSVAL_TRUE : JSVAL_FALSE;
return( JS_TRUE );
}
// Pause/unpause the game
JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* UNUSED(rval) )
{
REQUIRE_PARAMS( 1, setPaused );
try
{
g_Game->m_Paused = ToPrimitive<bool>( argv[0] );
}
catch( PSERROR_Scripting_ConversionFailed )
{
JS_ReportError( cx, "Invalid parameter to setPaused" );
}
return( JS_TRUE );
}
// Reveal map
JSBool revealMap( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
@ -1016,6 +1039,8 @@ JSFunctionSpec ScriptFunctionTable[] =
// Misc. Engine Interface
JS_FUNC(writeLog, WriteLog, 1)
JS_FUNC(exit, exitProgram, 0)
JS_FUNC(isPaused, isPaused, 0)
JS_FUNC(setPaused, setPaused, 1)
JS_FUNC(vmem, vmem, 0)
JS_FUNC(_rewriteMaps, _rewriteMaps, 0)
JS_FUNC(_lodbias, _lodbias, 0)

View File

@ -615,11 +615,11 @@ void CEntity::Tick()
DispatchEvent( &evt );
}
void CEntity::Damage( CDamageType& damage, CEntity* inflictor )
/*void CEntity::Damage( CDamageType& damage, CEntity* inflictor )
{
CEventDamage evt( inflictor, &damage );
DispatchEvent( &evt );
}
}*/
void CEntity::clearOrders()
@ -1017,7 +1017,7 @@ void CEntity::ScriptingInit()
AddMethod<bool, &CEntity::OrderSingle>( "order", 1 );
AddMethod<bool, &CEntity::OrderQueued>( "orderQueued", 1 );
AddMethod<bool, &CEntity::Kill>( "kill", 0 );
AddMethod<bool, &CEntity::Damage>( "damage", 1 );
//AddMethod<bool, &CEntity::Damage>( "damage", 1 );
AddMethod<bool, &CEntity::IsIdle>( "isIdle", 0 );
AddMethod<bool, &CEntity::HasClass>( "hasClass", 1 );
AddMethod<jsval, &CEntity::GetSpawnPoint>( "getSpawnPoint", 1 );
@ -1201,7 +1201,7 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued )
return( true );
}
bool CEntity::Damage( JSContext* cx, uintN argc, jsval* argv )
/*bool CEntity::Damage( JSContext* cx, uintN argc, jsval* argv )
{
CEntity* inflictor = NULL;
@ -1237,7 +1237,7 @@ bool CEntity::Damage( JSContext* cx, uintN argc, jsval* argv )
Damage( *dmg, inflictor );
return( true );
}
}*/
bool CEntity::Kill( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
{

View File

@ -215,7 +215,7 @@ public:
CPlayer* GetPlayer() { return m_player; }
// Process damage
void Damage( CDamageType& damage, CEntity* inflictor = NULL );
//void Damage( CDamageType& damage, CEntity* inflictor = NULL );
// Update collision patch (move ourselves to a new one if necessary)
void updateCollisionPatch();
@ -266,7 +266,7 @@ public:
jsval ToString( JSContext* cx, uintN argc, jsval* argv );
bool Damage( JSContext* cx, uintN argc, jsval* argv );
//bool Damage( JSContext* cx, uintN argc, jsval* argv );
bool Kill( JSContext* cx, uintN argc, jsval* argv );
jsval GetSpawnPoint( JSContext* cx, uintN argc, jsval* argv );

View File

@ -85,6 +85,8 @@ HEntity CEntityManager::create( CBaseEntity* base, CVector3D position, float ori
}
m_entities[m_nextalloc].m_entity = new CEntity( base, position, orientation );
if( m_collisionPatches)
m_entities[m_nextalloc].m_entity->updateCollisionPatch();
m_entities[m_nextalloc].m_entity->me = HEntity( m_nextalloc );
return( HEntity( m_nextalloc++ ) );
}
@ -166,19 +168,6 @@ void CEntityManager::GetInRange( float x, float z, float radius, std::vector<CEn
}
}
}
/*for( int i = 0; i < MAX_HANDLES; i++ )
{
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed && m_entities[i].m_entity->m_extant )
{
float dx = x - m_entities[i].m_entity->m_position.X;
float dz = z - m_entities[i].m_entity->m_position.Z;
if(dx*dx + dz*dz <= radius*radius)
{
results.push_back( m_entities[i].m_entity );
}
}
}*/
}
/*

View File

@ -524,7 +524,10 @@ bool CEntity::processHealNoPathing( CEntityOrder* current, size_t timestep_milli
bool CEntity::processGeneric( CEntityOrder* current, size_t timestep_millis )
{
int id = current->m_data[1].data;
debug_assert( m_actions.find( id ) != m_actions.end() );
if( m_actions.find( id ) == m_actions.end() )
{
return false; // we've been tasked as part of a group but we can't do this action
}
SEntityAction& action = m_actions[id];
return( processContactAction( current, timestep_millis, CEntityOrder::ORDER_GENERIC_NOPATHING, &action ) );
}
@ -532,7 +535,10 @@ bool CEntity::processGeneric( CEntityOrder* current, size_t timestep_millis )
bool CEntity::processGenericNoPathing( CEntityOrder* current, size_t timestep_millis )
{
int id = current->m_data[1].data;
debug_assert( m_actions.find( id ) != m_actions.end() );
if( m_actions.find( id ) == m_actions.end() )
{
return false; // we've been tasked as part of a group but we can't do this action
}
SEntityAction& action = m_actions[id];
CEventGeneric evt( current->m_data[0].entity, id );
if( !m_actor ) return( false );

View File

@ -8,7 +8,7 @@
class CEntityManager;
class CDamageType : public CJSObject<CDamageType>
/*class CDamageType : public CJSObject<CDamageType>
{
public:
float m_Crush;
@ -73,7 +73,7 @@ public:
return( JS_TRUE );
}
};
};*/
struct SEntityAction
{

View File

@ -28,13 +28,13 @@ CEventGeneric::CEventGeneric( CEntity* target, int action ) : CScriptEvent( L"ge
AddLocalProperty( L"action", &m_action );
}
CEventDamage::CEventDamage( CEntity* inflictor, CDamageType* damage ) : CScriptEvent( L"takesDamage", EVENT_DAMAGE, true )
/*CEventDamage::CEventDamage( CEntity* inflictor, CDamageType* damage ) : CScriptEvent( L"takesDamage", EVENT_DAMAGE, true )
{
m_inflictor = inflictor;
m_damage = damage;
AddLocalProperty( L"inflictor", &m_inflictor, true );
AddLocalProperty( L"damage", &m_damage );
}
}*/
CEventTargetChanged::CEventTargetChanged( CEntity* target ) : CScriptEvent( L"targetChanged", EVENT_TARGET_CHANGED, false )
{

View File

@ -36,13 +36,13 @@ public:
CEventGather( CEntity* target );
};
class CEventDamage : public CScriptEvent
/*class CEventDamage : public CScriptEvent
{
CEntity* m_inflictor;
CDamageType* m_damage;
public:
CEventDamage( CEntity* inflictor, CDamageType* damage );
};
};*/
class CEventHeal : public CScriptEvent
{