etqw-sdk/base/script/misc/supply_crate.script

614 lines
15 KiB
Plaintext
Raw Normal View History

2008-05-29 00:00:00 +00:00
object supply_crate {
void preinit();
void syncFields();
void init();
void destroy();
float OnUpdateCrosshairInfo( entity p );
void OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location );
void vSetDeployableOwner( entity p );
void OnOwnerChanged();
void vOnDeploy();
void OnDeployedChanged() { vOnDeploy(); }
void Idle();
void Supply();
void LogLifeTime();
void SetupCommandMap();
void UpdateGUI();
void Fizzle();
void RemoveThread( float removeTime );
void vRemoveObject() { Fizzle(); }
boolean vIsSupplyDrop() { return true; }
float vGetSupplyDropCreationTime();
boolean vBlockVehicleSpawn() { return true; }
void vOnBindMasterDestroyed();
void BoundsKillThread();
void DropSoundThread();
void HideParachute();
void OnFizzleChanged();
void OnSupplyCountChanged();
void vBindToEntity( entity ent );
boolean vDropItemTrace( vector tStart, vector tEnd, entity passEntity, vector targetPos );
boolean ValidDropTrace( vector originalPos );
boolean vAllowDrop();
float GetSupplyCrateIndex();
float GetSupplyCrateCount();
float supplyCount;
float supplyMax;
float lastSupplyCount;
float creationTime;
float repairRange;
float commandMapHandle;
float commandMapHandleEnemy;
string packageName;
player owner;
entity vGetOwner() { return owner; }
handle objectName;
float usedProficiency;
handle statUsed;
handle statTimeUsed;
handle statNumDestroyed;
boolean removeThreadActive;
boolean deployed;
boolean fizzle;
entity bindEntity;
boolean allowDrop;
}
void supply_crate::syncFields() {
syncBroadcast( "supplyCount" );
syncBroadcast( "owner" );
syncBroadcast( "deployed" );
syncBroadcast( "fizzle" );
syncCallback( "owner", "OnOwnerChanged" );
syncCallback( "deployed", "OnDeployedChanged" );
syncCallback( "fizzle", "OnFizzleChanged" );
syncCallback( "supplyCount", "OnSupplyCountChanged" );
}
void supply_crate::preinit() {
repairRange = MetresToInches( getFloatKeyWithDefault( "repair_range", 2.5f ) );
packageName = getKey( "pck_items" );
supplyMax = getFloatKeyWithDefault( "max_supply", 50.f );
supplyCount = supplyMax;
lastSupplyCount = supplyMax;
objectName = sys.localizeString( getKey( "object_name" ) );
usedProficiency = GetProficiency( getKey( "prof_used" ) );
creationTime = sys.getTime();
commandMapHandle = -1;
commandMapHandleEnemy = -1;
statUsed = -1;
statTimeUsed = -1;
statNumDestroyed = -1;
string statName = getKey( "stat_name" );
if ( statName != "" ) {
statUsed = sys.allocStatInt( statName + "_uses" );
statTimeUsed = sys.allocStatInt( statName + "_time_used" );
statNumDestroyed = sys.allocStatInt( statName + "_killed" );
}
creationTime = sys.getTime();
setContents( CONTENTS_RENDERMODEL | CONTENTS_PLAYERCLIP | CONTENTS_VEHICLECLIP | CONTENTS_FLYERHIVECLIP );
}
void supply_crate::init() {
SetupCommandMap();
if ( !sys.isClient() ) {
owner.binAdd( self );
player p = owner;
if ( p != $null_entity ) {
p.setPlayerSupplyCrateState( self, false );
}
}
setState( "Idle" );
}
void supply_crate::destroy() {
sys.freeCMIcon( self, commandMapHandle );
sys.freeCMIcon( self, commandMapHandleEnemy );
LogLifeTime();
sys.killThread( "RemoveThread_" + getName() );
if ( !sys.isClient() ) {
player p = owner;
if ( p != $null_entity ) {
p.setPlayerSupplyCrateState( self, true );
}
}
if( owner == sys.getLocalPlayer() ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateHealth0", 0 );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateSupplies0", 0 );
float count = GetSupplyCrateCount();
if ( count < 2 ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateHealth1", 0 );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateSupplies1", 0 );
}
}
if ( owner != $null_entity ) {
owner.binRemove( self );
}
}
void supply_crate::vOnDeploy() {
if ( !sys.isClient() ) {
deployed = true;
G_GiveDeployBonus( owner, self );
}
float hitGroundEffect = getFloatKey( "play_hitground_effect" );
if ( hitGroundEffect ) {
startSound( "snd_drop", SND_DEPLOYABLE_IDLE );
playEffect( "fx_hitground", "origin", false );
}
}
void supply_crate::LogLifeTime() {
if ( owner == $null_entity ) {
return;
}
float t = sys.getTime() - creationTime;
sys.increaseStatInt( statTimeUsed, owner.getEntityNumber(), t );
}
void supply_crate::Idle() {
if ( sys.isClient() ) {
return;
}
sys.wait( 0.1f );
thread BoundsKillThread();
while ( true ) {
if ( isAtRest() ) {
if ( bindEntity != $null_entity ) {
if ( !sys.isClient() ) {
bind( bindEntity );
}
}
if ( !removeThreadActive ) {
thread DropSoundThread();
}
break;
}
sys.waitFrame();
}
sys.killThread( "BoundsKillThread_" + getName() );
while ( true ) {
sys.wait( 1.f );
if ( !removeThreadActive ) {
Supply();
}
}
}
void supply_crate::Supply() {
vector mins, maxs;
mins = getAbsMins() - '32 32 0';
maxs = getAbsMaxs() + '32 32 8';
entitiesInBounds( mins, maxs, CONTENTS_BODY | CONTENTS_SLIDEMOVER, 1.0f );
filterEntitiesByClass( "idPlayer", 1 );
float count = filterEntitiesByAllegiance( TA_FLAG_FRIEND, 1 );
float i;
for ( i = 0; i < count; i++ ) {
entity p = getBoundsCacheEntity( i );
if ( p.getHealth() <= 0 ) {
continue;
}
if ( p.givePackage( packageName ) ) {
supplyCount = supplyCount - 1;
OnSupplyCountChanged();
if ( owner != $null_entity ) {
if ( owner != p ) {
if ( usedProficiency != -1 ) {
owner.giveProficiency( usedProficiency, 1.f, $null, "supply crate used" );
}
sys.increaseStatInt( statUsed, owner.getEntityNumber(), 1 );
}
}
if ( supplyCount == 0 ) {
vRemoveObject();
}
}
}
}
void supply_crate::SetupCommandMap() {
commandMapHandle = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm" ) );
float commandMapSize = getFloatKeyWithDefault( "icon_size_cm", 16.f );
sys.setCMIconDrawMode( commandMapHandle, DM_ROTATED_MATERIAL );
sys.setCMIconSize( commandMapHandle, commandMapSize );
sys.setCMIconColorMode( commandMapHandle, CM_ALLEGIANCE );
sys.setCMIconMaterial( commandMapHandle, GetMaterial( getKey( "mtr_commandmap" ) ) );
sys.setCMIconFlag( commandMapHandle, CMF_ALWAYSKNOWN | CMF_TEAMONLY );
commandMapHandleEnemy = sys.allocCMIcon( self, getFloatKey( "icon_sort_cm" ) );
sys.setCMIconDrawMode( commandMapHandleEnemy, DM_ROTATED_MATERIAL );
sys.setCMIconSize( commandMapHandleEnemy, commandMapSize );
sys.setCMIconColorMode( commandMapHandleEnemy, CM_ALLEGIANCE );
sys.setCMIconMaterial( commandMapHandleEnemy, GetMaterial( getKey( "mtr_commandmap" ) ) );
sys.setCMIconFlag( commandMapHandleEnemy, CMF_ENEMYONLY );
}
float supply_crate::OnUpdateCrosshairInfo( entity p ) {
if ( !sys.doClientSideStuff() ) {
return 1.f;
}
float allegiance = getEntityAllegiance( p );
vector color = GetAllegianceColor( allegiance );
chSetNumLines( 0 );
float index;
index = chAddLine();
chSetLineColor( index, color, 1.f );
chSetLineTextIndex( index, objectName );
chSetLineType( index, CI_TEXT );
chSetLineSize( index, 0, 0 );
index = chAddLine();
chSetLineColor( index, color, 0.5f );
chSetLineType( index, CI_BAR );
chSetLineFraction( index, getHealth() / getMaxHealth() );
chSetLineSize( index, 100, CROSSHAIR_INFO_BAR_HEIGHT );
if ( allegiance == TA_FRIEND ) {
index = chAddLine();
chSetLineTextIndex( index, g_locStr_Supplies );
chSetLineColor( index, color, 1.f );
chSetLineType( index, CI_TEXT );
chSetLineSize( index, 0, 0 );
index = chAddLine();
chSetLineColor( index, color, 0.5f );
chSetLineType( index, CI_BAR );
chSetLineFraction( index, supplyCount / supplyMax );
chSetLineSize( index, 100, CROSSHAIR_INFO_BAR_HEIGHT );
}
return 1.f;
}
void supply_crate::OnKilled( entity inflictor, entity attacker, float damage, vector direction, float location ) {
if ( !sys.isClient() ) {
player attackPlayer = attacker;
if ( attackPlayer != $null_entity ) {
if ( getEntityAllegiance( inflictor ) == TA_ENEMY ) {
sys.increaseStatInt( statNumDestroyed, attackPlayer.getEntityNumber(), 1 );
}
}
Fizzle();
entity next;
entity current;
for ( current = getNextTeamEntity(); current != $null_entity; current = next ) {
next = current.getNextTeamEntity();
current.vOnBindMasterDestroyed();
}
}
}
void supply_crate::vSetDeployableOwner( entity p ) {
owner = p;
OnOwnerChanged();
}
void supply_crate::UpdateGUI() {
sys.threadName( "UpdateGUI_" + getName() );
while( true ) {
if ( !removeThreadActive ) {
float index = GetSupplyCrateIndex();
if ( index == 0 ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateHealth0", getHealth() / getMaxHealth() );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateSupplies0", supplyCount / supplyMax );
if ( GetSupplyCrateCount() == 1 ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateHealth1", 0 );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateSupplies1", 0 );
}
} else if ( index == 1 ) {
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateHealth1", getHealth() / getMaxHealth() );
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.supplyCrateSupplies1", supplyCount / supplyMax );
}
}
sys.waitFrame();
}
}
void supply_crate::OnOwnerChanged() {
if ( owner == sys.getLocalPlayer() ) {
sys.killThread( "UpdateGUI_" + getName() );
thread UpdateGUI();
}
}
void supply_crate::BoundsKillThread() {
float damageIndex = GetDamage( getKey( "dmg_crush" ) );
while ( true ) {
vector mins = getAbsMins();
vector maxs = getAbsMaxs();
mins += '8 8 -32';
maxs -= '8 8 0';
float count = entitiesInBounds( mins, maxs, MASK_SHOT_RENDERMODEL | MASK_SHOT_BOUNDINGBOX, 1 );
float index;
for ( index = 0; index < count; index++ ) {
entity other = getBoundsCacheEntity( index );
if ( other == self ) {
continue;
}
if ( other != $null_entity ) {
other.applyDamage( $null_entity, self, '0 0 -1', damageIndex, 1.f, $null_entity );
}
vehicle_base v = other;
if ( v != $null_entity ) {
vRemoveObject();
}
}
if ( removeThreadActive ) {
return;
}
sys.waitFrame();
}
}
void supply_crate::Fizzle() {
if ( removeThreadActive ) {
return;
}
startSound( "snd_drop", SND_DEPLOYABLE );
playEffect( "fx_fizzle", "", 0 );
HideParachute();
hide();
disablePhysics();
forceDisableClip();
removeThreadActive = true;
fizzle = true;
if ( !sys.isClient() ) {
thread RemoveThread( 2.0 );
}
}
void supply_crate::RemoveThread( float removeTime ) {
sys.wait( removeTime );
remove();
}
float supply_crate::vGetSupplyDropCreationTime() {
return creationTime;
}
void supply_crate::DropSoundThread() {
startSound( "snd_drop", SND_DEPLOYABLE );
}
void supply_crate::HideParachute() {
if ( !sys.isClient() ) {
float index;
float count = entitiesOfCollection( "parachutes" );
for ( index = 0; index < count; index++ ) {
entity other = getBoundsCacheEntity( index );
if ( other.vGetOwner() == self ) {
other.vCancel();
return;
}
}
}
}
void supply_crate::OnFizzleChanged() {
if ( sys.isClient() ) {
Fizzle();
}
}
void supply_crate::OnSupplyCountChanged() {
entity p = sys.getLocalPlayer();
if ( p == $null_entity ) {
return;
}
if ( supplyCount < lastSupplyCount ) {
startSound( "snd_supply", SND_DEPLOYABLE_IDLE );
}
lastSupplyCount = supplyCount;
}
void supply_crate::vOnBindMasterDestroyed() {
if ( !sys.isClient() ) {
unbind();
Fizzle();
}
}
void supply_crate::vBindToEntity( entity ent ) {
bindEntity = ent;
}
boolean supply_crate::vDropItemTrace( vector tStart, vector tEnd, entity passEntity, vector targetPos ) {
allowDrop = true;
float frac = sys.tracePoint( tStart, tEnd, CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
vector pos = sys.getTraceEndPos() + '0 0 1'; // just a tiny bit off of ground as it might not be flat
if ( frac == 1.0f || sys.getTraceNormal() * vec3_up < 0.99f ) {
if ( sys.fabs( pos_z - targetPos_z ) > 128 ) {
allowDrop = false;
}
return true;
}
// try to avoid clipping into buildings
if ( !sys.checkContents( pos, getMins(), getMaxs(), CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity ) ) {
if ( sys.fabs( pos_z - targetPos_z ) > 128 ) {
allowDrop = false;
}
return true;
}
vector size = getSize();
pos_x = pos_x + size_x / 2;
pos_y = pos_y + size_y / 2;
vector cratePos;
cratePos_x = pos_x - size_x;
cratePos_y = pos_y - size_y;
cratePos_z = pos_z;
sys.trace( cratePos + '0 0 2048', cratePos + '0 0 -128', getMins(), getMaxs(), CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
if ( ValidDropTrace( cratePos ) ) {
return true;
}
cratePos_x = pos_x;
cratePos_y = pos_y - size_y;
sys.trace( cratePos + '0 0 2048', cratePos + '0 0 -128', getMins(), getMaxs(), CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
if ( ValidDropTrace( cratePos ) ) {
return true;
}
cratePos_x = pos_x - size_x;
cratePos_y = pos_y;
sys.trace( cratePos + '0 0 2048', cratePos + '0 0 -128', getMins(), getMaxs(), CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
if ( ValidDropTrace( cratePos ) ) {
return true;
}
cratePos_x = pos_x;
cratePos_y = pos_y;
sys.trace( cratePos + '0 0 2048', cratePos + '0 0 -128', getMins(), getMaxs(), CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
if ( ValidDropTrace( cratePos ) ) {
return true;
}
sys.tracePoint( tStart, tEnd, CONTENTS_SOLID | CONTENTS_MOVEABLECLIP | CONTENTS_PLAYERCLIP, passEntity );
if ( sys.fabs( pos_z - targetPos_z ) > 128 ) {
allowDrop = false;
}
return true;
}
boolean supply_crate::ValidDropTrace( vector originalPos ) {
vector pos = sys.getTraceEndPos();
if ( sys.fabs( pos_z - originalPos_z ) > 4 ) {
return false;
}
if ( sys.getTraceFraction() == 1.0f
|| ( sys.getTraceNormal() * vec3_up < 0.99f )
|| ( sys.getTraceSurfaceFlags() & SURF_NOIMPACT )
|| ( sys.getTraceEntity() != $null_entity && sys.getTraceEntity() != sys.getEntity( "worldspawn" ) ) ) {
return false;
}
return true;
}
float supply_crate::GetSupplyCrateIndex() {
if ( owner == $null_entity ) {
return -1;
}
float i;
float num = owner.binGetSize();
float index = 0;
for ( i = 0; i < num; i++ ) {
entity other = owner.binGet( i );
if ( other.inCollection( "supply_crate" ) ) {
if ( other == self ) {
return index;
} else {
index++;
}
}
}
return -1;
}
float supply_crate::GetSupplyCrateCount() {
if ( owner == $null_entity ) {
return 0;
}
float i;
float num = owner.binGetSize();
float count = 0;
for ( i = 0; i < num; i++ ) {
entity other = owner.binGet( i );
if ( other.inCollection( "supply_crate" ) ) {
count++;
}
}
return count;
}
boolean supply_crate::vAllowDrop() {
return allowDrop;
}