/* ================ ClientEvents Events will be passed on to the clients for presentation, but any server game effects are handled here ================ */ void ClientEvents( gentity_t *ent, int oldEventSequence ) { int i; int event; gclient_t *client; int damage; qboolean fired; client = ent->client; fired = qfalse; for ( i = oldEventSequence ; i < client->ps.eventSequence ; i++ ) { event = client->ps.events[ i & (MAX_PS_EVENTS-1) ]; switch ( event ) { case EV_FALL_MEDIUM: case EV_FALL_FAR://these come from bg_pmove, PM_CrashLand if ( ent->s.eType != ET_PLAYER ) { break; // not in the player model } //FIXME: isn't there a more accurate way to calculate damage from falls? if ( event == EV_FALL_FAR ) { damage = 50; } else { damage = 25; } ent->painDebounceTime = level.time + 200; // no normal pain sound G_Damage (ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING); break; case EV_FIRE_WEAPON: #ifndef FINAL_BUILD if ( fired ) { gi.Printf( "DOUBLE EV_FIRE_WEAPON AND-OR EV_ALT_FIRE!!\n" ); } #endif fired = qtrue; FireWeapon( ent, qfalse ); break; case EV_ALT_FIRE: #ifndef FINAL_BUILD if ( fired ) { gi.Printf( "DOUBLE EV_FIRE_WEAPON AND-OR EV_ALT_FIRE!!\n" ); } #endif fired = qtrue; FireWeapon( ent, qtrue ); break; default: break; } } }
void AMainCharacter::StartFire() { UWorld* World = GetWorld(); if (World) { if (CurrentWeapon != NULL) { if (CurrentWeapon->Config.bIsAutomatic == true) { World->GetTimerManager().SetTimer( AutomaticFireTimerHandle, this, &AMainCharacter::FireWeapon, CurrentWeapon->Config.FireRate, true, 0.0f); } else if (bFireIsReady) { World->GetTimerManager().ClearTimer(SingleFireTimerHandle); World->GetTimerManager().SetTimer( SingleFireTimerHandle, this, &AMainCharacter::FireIsReady, CurrentWeapon->Config.FireRate, true, CurrentWeapon->Config.FireRate); FireWeapon(); bFireIsReady = false; } } } }
// ----------------------------------------------------------------------- // // // ROUTINE: GunMount::StartFiring // // PURPOSE: Starts the firing state. // // ----------------------------------------------------------------------- // bool GunMount::StartFiring( ) { CWeapon* pWeapon = m_Arsenal.GetCurWeapon( ); if( !pWeapon ) return false; // Play the fire animation if they have it. HMODELANIM hAnim = pWeapon->GetFireAni( ); if( hAnim != INVALID_ANI ) { pWeapon->PlayAnimation( hAnim, true, false ); } // Fire the weapon. if( !FireWeapon( )) { return StartNotFiring( ); } m_eFiringState = eFiring; SetNextUpdate( UPDATE_NEXT_FRAME ); return true; }
void AAWeapon::HandleFiring() { if (CurrentAmmoInClip > 0 && CanFire()) { if (GetNetMode() != NM_DedicatedServer) { SimulateWeaponFire(); } if (MyPawn && MyPawn->IsLocallyControlled()) { FireWeapon(); UseAmmo(); BurstCounter++; } } else if (CanReload()) { StartReload(); } else if (MyPawn && MyPawn->IsLocallyControlled()) { if (GetCurrentAmmo() == 0 && !bRefiring) { PlayWeaponSound(OutOfAmmoSound); } /* Reload after firing last round */ if (CurrentAmmoInClip <= 0 && CanReload()) { StartReload(); } /* Stop weapon fire FX, but stay in firing state */ if (BurstCounter > 0) { OnBurstFinished(); } } if (MyPawn && MyPawn->IsLocallyControlled()) { if (Role < ROLE_Authority) { ServerHandleFiring(); } /* Retrigger HandleFiring on a delay for automatic weapons */ bRefiring = (CurrentState == EWeaponState::Firing && TimeBetweenShots > 0.0f); if (bRefiring) { GetWorldTimerManager().SetTimer(TimerHandle_HandleFiring, this, &AAWeapon::HandleFiring, TimeBetweenShots, false); } } LastFireTime = GetWorld()->GetTimeSeconds(); }
void CCharacter::HandleWeapons() { //ninja HandleNinja(); // check reload timer if(m_ReloadTimer) { m_ReloadTimer--; return; } // fire Weapon, if wanted FireWeapon(); // ammo regen int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; if(AmmoRegenTime) { // If equipped and not active, regen ammo? if (m_ReloadTimer <= 0) { if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0) m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick(); if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000) { // Add some ammo m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10); m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } else { m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } /* INFECTION MODIFICATION START ***************************************/ if(GetClass() == PLAYERCLASS_ZOMBIE) { if(m_Core.m_HookedPlayer >= 0) { CCharacter *VictimChar = GameServer()->GetPlayerChar(m_Core.m_HookedPlayer); if(VictimChar) { if(m_PoisonTick + Server()->TickSpeed()*0.5 < Server()->Tick()) { m_PoisonTick = Server()->Tick(); VictimChar->TakeDamage(vec2(0.0f,0.0f), 1, m_pPlayer->GetCID(), WEAPON_NINJA); } } } } /* INFECTION MODIFICATION END *****************************************/ return; }
void Bot::ActiveFrame() { //get ready if in the game if(GS_MatchState() <= MATCH_STATE_WARMUP && !IsReady() && self->r.client->teamstate.timeStamp + 4000 < level.time) G_Match_Ready(self); ApplyPendingTurnToLookAtPoint(); const CombatTask &combatTask = botBrain.combatTask; bool inhibitShooting, inhibitCombatMove; SetCombatInhibitionFlags(&inhibitShooting, &inhibitCombatMove); // ucmd modification in FireWeapon() will be overwritten by MoveFrame() bool fireButtonPressed = false; if (!inhibitShooting) { SetCloakEnabled(false); // If bot fired builtin or script weapon, save builtin fire button status FireWeapon(&fireButtonPressed); } else { if (!combatTask.Empty()) { SetCloakEnabled(true); } else if (botBrain.HasGoal()) { if (botBrain.IsCloseToAnyGoal(768.0f, true)) SetCloakEnabled(true); else if (botBrain.IsCloseToAnyGoal(384.0f, false)) SetCloakEnabled(true); else SetCloakEnabled(false); } else { SetCloakEnabled(false); } } bool beSilent = ShouldBeSilent(inhibitShooting); // Do not modify pmove features by beSilent value, features may be changed dynamically by script. usercmd_t ucmd; memset(&ucmd, 0, sizeof(ucmd)); MoveFrame(&ucmd, inhibitCombatMove, beSilent); if (fireButtonPressed) ucmd.buttons |= BUTTON_ATTACK; CallActiveClientThink(&ucmd); SayVoiceMessages(); }
void AWeapon::HandleFiring() { if ((CurrentAmmoInClip > 0 || HasInfiniteClip() || HasInfiniteAmmo()) && CanFire()) { if (GetNetMode() != NM_DedicatedServer) { SimulateWeaponFire(); } if (MyPawn && MyPawn->IsLocallyControlled()) { FireWeapon(); UseAmmo(); // update firing FX on remote clients if function was called on server BurstCounter++; } } else if (CanReload()) { StartReload(); } else if (MyPawn && MyPawn->IsLocallyControlled()) { // stop weapon fire FX, but stay in Firing state if (BurstCounter > 0) { OnBurstFinished(); } } if (MyPawn && MyPawn->IsLocallyControlled()) { // local client will notify server if (Role < ROLE_Authority) { ServerHandleFiring(); } // reload after firing last round if (CurrentAmmoInClip <= 0 && CanReload()) { StartReload(); } // setup refire timer bRefiring = (CurrentState == EWeaponState::Firing && WeaponConfig.TimeBetweenShots > 0.0f); if (bRefiring) { GetWorldTimerManager().SetTimer(TimerHandle_HandleFiring, this, &AWeapon::HandleFiring, WeaponConfig.TimeBetweenShots, false); } } LastFireTime = GetWorld()->GetTimeSeconds(); }
void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput) { mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput)); if(m_NumInputs > 2 && m_pPlayer->GetTeam() != TEAM_SPECTATORS) { HandleWeaponSwitch(); FireWeapon(); } mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); }
void CCharacter::HandleWeapons() { //ninja HandleNinja(); // check reload timer if(m_ReloadTimer) { m_ReloadTimer--; return; } // fire Weapon, if wanted FireWeapon(); // ammo regen int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; if(m_aWeapons[m_ActiveWeapon].m_Ammo > -1) { switch(m_ActiveWeapon) { case WEAPON_GUN: AmmoRegenTime = 125*5; break; case WEAPON_GRENADE: AmmoRegenTime = 1000; break; case WEAPON_RIFLE: AmmoRegenTime = 1200; break; case WEAPON_SHOTGUN: AmmoRegenTime = 1000; break; } } if(AmmoRegenTime) { // If equipped and not active, regen ammo? if (m_ReloadTimer <= 0) { if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0) m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick(); if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000) { // Add some ammo m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10); m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } else { m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } return; }
void CStaticStructure::ProcessFrame(unsigned int dwCurrentTime,double dTimeFraction) { CEntityBase::ProcessFrame(dwCurrentTime,dTimeFraction); m_dwNextProcessFrame=dwCurrentTime+10; if(GetState()==eStaticStructureState_Destroyed){return;} if(GetState()==eStaticStructureState_Normal) { size_t nAnimationToSet=0; double dMaxHealth=GetMaxHealth(); unsigned int nAnimations=m_pTypeBase->GetStateAnimations(ENTITY_STATE_BASE); nAnimationToSet=(size_t)(((dMaxHealth-m_dHealth)/dMaxHealth)*((double)nAnimations)); if(nAnimationToSet>nAnimations-1){nAnimationToSet=nAnimations-1;} SetState(ENTITY_STATE_BASE,(int)nAnimationToSet); } bool bAllChildDead=true; for(unsigned int x=0;x<m_vChildren.size();x++){if(m_vChildren[x].piEntity->GetHealth()>0){bAllChildDead=false;}} m_dwDamageType=(bAllChildDead?m_nConfiguredDamageType:DAMAGE_TYPE_NONE); if(m_dwAlignment==ENTITY_ALIGNMENT_ENEMIES) { GetTarget(); } if(m_piTarget && dwCurrentTime>m_dwNextShotTime && m_vWeapons.size()) { bool bVisible=g_PlayAreaManagerWrapper.m_piInterface && g_PlayAreaManagerWrapper.m_piInterface->IsVisible(m_PhysicInfo.vPosition,0); if(bVisible) { double dDifficulty=g_PlayerManagerWrapper.m_piInterface->GetEffectiveDifficulty(); double dTimeFirstShotMin=m_pType->m_dTimeFirstShotMin/dDifficulty; double dTimeFirstShotMax=m_pType->m_dTimeFirstShotMax/dDifficulty; double dTimeBetweenShotsMin=m_pType->m_dTimeBetweenShotsMin/dDifficulty; double dTimeBetweenShotsMax=m_pType->m_dTimeBetweenShotsMax/dDifficulty; if(m_bFirstTimeVisible) { m_bFirstTimeVisible=false; m_dwNextShotTime=dwCurrentTime+drand()*(dTimeFirstShotMax-dTimeFirstShotMin)+dTimeFirstShotMin; } else { for(unsigned int x=0;x<m_vWeapons.size();x++){FireWeapon(x,dwCurrentTime);} m_dwNextShotTime=dwCurrentTime+drand()*(dTimeBetweenShotsMax-dTimeBetweenShotsMin)+dTimeBetweenShotsMin; } } } }
/*QUAKED misc_weapon_shooter (1 0 0) (-8 -8 -8) (8 8 8) ALTFIRE TOGGLE ALTFIRE - fire the alt-fire of the chosen weapon TOGGLE - keep firing until used again (fires at intervals of "wait") "wait" - debounce time between refires (defaults to 500) "delay" - speed of WP_THERMAL (default is 900) "random" - ranges from 0 to random, added to wait (defaults to 0) "target" - what to aim at (will update aim every frame if it's a moving target) "weapon" - specify the weapon to use (default is WP_BLASTER) WP_BRYAR_PISTOL WP_BLASTER WP_DISRUPTOR WP_BOWCASTER WP_REPEATER WP_DEMP2 WP_FLECHETTE WP_ROCKET_LAUNCHER WP_CONCUSSION WP_THERMAL WP_TRIP_MINE WP_DET_PACK WP_STUN_BATON WP_EMPLACED_GUN WP_BOT_LASER WP_TURRET WP_ATST_MAIN WP_ATST_SIDE WP_TIE_FIGHTER WP_RAPID_FIRE_CONC WP_BLASTER_PISTOL */ void misc_weapon_shooter_fire( gentity_t *self ) { FireWeapon( self, (self->spawnflags&1) ); if ( (self->spawnflags&2) ) {//repeat self->e_ThinkFunc = thinkF_misc_weapon_shooter_fire; if (self->random) { self->nextthink = level.time + self->wait + (int)(random()*self->random); } else { self->nextthink = level.time + self->wait; } } }
void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput) { mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput)); // it is not allowed to aim in the center if(m_LatestInput.m_TargetX == 0 && m_LatestInput.m_TargetY == 0) m_LatestInput.m_TargetY = -1; if(m_NumInputs > 2 && m_pPlayer->GetTeam() != TEAM_SPECTATORS) { HandleWeaponSwitch(); FireWeapon(); } mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); }
void WeaponController::SendMsg(EntityPtr e1, EntityPtr e2, Message::Message message) { switch (message) { case Message::MV_Space: try { FireWeapon(ENGINE->GetActiveSpace()->GetEntityByName("Player")); } catch (...) { // The player doesn't exist. } default: break; } }
void CCharacter::HandleWeapons() { //ninja HandleNinja(); vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); // check reload timer if(m_ReloadTimer) { m_ReloadTimer--; return; } // fire Weapon, if wanted FireWeapon(); // ammo regen int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; if(AmmoRegenTime) { // If equipped and not active, regen ammo? if (m_ReloadTimer <= 0) { if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0) m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick(); if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000) { // Add some ammo m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10); m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } else { m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } return; }
void ASWeapon::HandleFiring() { if (CanFire()) { if (GetNetMode() != NM_DedicatedServer) { SimulateWeaponFire(); } if (MyPawn && MyPawn->IsLocallyControlled()) { FireWeapon(); // TODO: Consume Ammo // Update firing FX on remote clients if this is called on server // Cause it is replicated value on server. BurstCounter++; } } // TODO: End repeat fire if ammo runs dry if (MyPawn && MyPawn->IsLocallyControlled()) { if (Role < ROLE_Authority) { ServerHanleFiring(); } // TODO: if weapon is automatic firing rifle -> Setup refiring timer. (calls HandleFiring()) bRefiring = (CurrentState == EWeaponState::Firing && TimeBetweenShots > 0.0f); if (bRefiring) { GetWorldTimerManager().SetTimer(HandleFiringTimerHandle, this, &ASWeapon::HandleFiring, TimeBetweenShots, false); } } LastFireTime = GetWorld()->GetTimeSeconds(); }
void CCharacter::HandleWeapons() { //ninja HandleNinja(); // check reload timer if(m_ReloadTimer) { m_ReloadTimer--; return; } // fire Weapon, if wanted FireWeapon(); // ammo regen int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; if(AmmoRegenTime && m_aWeapons[m_ActiveWeapon].m_Ammo >= 0) { // If equipped and not active, regen ammo? if (m_ReloadTimer <= 0) { if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0) m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick(); if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000) { // Add some ammo m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Maxammo); m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } else { m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } return; }
void AMagicBattleSoccerWeapon::HandleFiring() { if (CanFire()) { if (MyPawn && MyPawn->IsLocallyControlled()) { FireWeapon(); } } if (nullptr != MyPawn && MyPawn->IsLocallyControlled()) { // local client will notify server if (Role < ROLE_Authority) { ServerHandleFiring(); } // Make the player aim in the direction they're firing if they're not running AMagicBattleSoccerPlayerController* const PlayerController = Instigator ? Cast<AMagicBattleSoccerPlayerController>(Instigator->Controller) : nullptr; if (nullptr != PlayerController && nullptr != PlayerController->GetPawn() && nullptr != PlayerController->GetPawn()->GetMovementComponent() && PlayerController->GetPawn()->GetMovementComponent()->Velocity.Size() < 0.001f) { // We can't aim immediately because that could put the camera out of sync with the pawn. Just assign ourselves to the controller and it // will take care of things in the next Tick(). PlayerController->bFaceMouseCursorInTick = true; } // setup refire timer bRefiring = (LocalState == EWeaponState::Firing && WeaponConfig.TimeBetweenShots > 0.0f && WeaponConfig.RepeatingFire); if (bRefiring) { // Start a timer to handle repeating firing GetWorldTimerManager().SetTimer(TimerHandle_HandleFiringTimer, this, &AMagicBattleSoccerWeapon::HandleFiring, WeaponConfig.TimeBetweenShots, false); } } LastFireTime = GetWorld()->GetTimeSeconds(); }
void InputDevice::ProcessKeyboard() { Vehicle* v = vehicleContainer->get(0); float orientation[3]; v->getOrientation(orientation); float currentSpeed = v->getSpeed(); if (GetKeyState(VK_LBUTTON) < 0) { FireWeapon(0, NULL); } if (GetKeyState(VK_LEFT) < 0 || GetKeyState(VK_a) < 0) { float amount = 0.15f; if(v->getSpeed() < -0.05f) amount*=-1.0f; v->setRateOfTurn(v->getRateOfTurn() - amount); } if (GetKeyState(VK_UP) < 0 || GetKeyState(VK_w) < 0) { v->setSpeed( currentSpeed + 0.05f); } if (GetKeyState(VK_RIGHT) < 0 || GetKeyState(VK_d) < 0) { float amount = 0.15f; if(v->getSpeed() < -0.05f) amount*=-1.0f; v->setRateOfTurn(v->getRateOfTurn() + amount); } if (GetKeyState(VK_DOWN) < 0 || GetKeyState(VK_s) < 0) { v->setSpeed( currentSpeed - 0.05f); } }
/* Alien Nuke */ qboolean Alien_nuke( gentity_t *ent, int skiparg ) { //vic->client->ps.persistant[ PERS_CREDIT ] if( ent->client->ps.persistant[ PERS_CREDIT ] < 9 ) { PM_AddEvent( EV_NOAMMO ); ent->client->ps.weaponTime += 200; trap_SendServerCommand( ent-g_entities, va( "print \"^1You must have 9 evos\n\"" ) ); return qtrue; } trap_SendServerCommand( ent-g_entities, va( "print \"^1Nade Dropped\n\"" ) ); //G_TeamCommand( PTE_HUMANS, "cp \"^1Alien Nuke Detected\" 1"); ent->s.weapon = WP_GRENADE; //G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, 0 ); FireWeapon( ent ); ent->client->ps.persistant[ PERS_CREDIT ] = 0; ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; return qtrue; }
void PDoWeapons(void) { // switching weapons. have to check for inputs_frozen since justpushed // reads inputs[] directly, not pinputs[]. if (!player->inputs_locked) { if (justpushed(PREVWPNKEY)) stat_PrevWeapon(); if (justpushed(NEXTWPNKEY)) stat_NextWeapon(); } // firing weapon if (pinputs[FIREKEY]) { FireWeapon(); RunWeapon(true); } else { RunWeapon(false); } PHandleSpur(); run_whimstar(&player->whimstar); if (empty_timer) empty_timer--; }
void GunMount::UpdateFiring( ) { SetNextUpdate( UPDATE_NEXT_FRAME ); // If we're done, then go to post fire. if( m_nRoundsToFire == 0 ) { StartPostFiring( ); return; } CWeapon* pWeapon = m_Arsenal.GetCurWeapon( ); if( !pWeapon ) { StartPostFiring( ); return; } // Check if we had a fire anim to go off of. HMODELANIM hAnim = pWeapon->GetFireAni( ); if( hAnim != INVALID_ANI ) { // Check if we're still finishing the fire animation. if( !IsAnimationComplete( )) return; // Start it up for the next fire. pWeapon->PlayAnimation( hAnim, true, false ); } // Continue to fire weapon. if( !FireWeapon( )) { StartPostFiring( ); return; } }
void Player::Update(float dt) { SPADES_MARK_FUNCTION(); auto* listener = world->GetListener(); MovePlayer(dt); if(!IsAlive()) { // do death cleanup blockCursorDragging = false; } if(tool == ToolSpade){ if(weapInput.primary){ if(world->GetTime() > nextSpadeTime){ UseSpade(); nextSpadeTime = world->GetTime() + GetToolPrimaryDelay(); } }else if(weapInput.secondary){ if(world->GetTime() > nextDigTime){ DigWithSpade(); nextDigTime = world->GetTime() + GetToolSecondaryDelay(); firstDig = false; } } }else if(tool == ToolBlock && IsLocalPlayer()){ GameMap::RayCastResult result; auto *map = GetWorld()->GetMap(); result = map->CastRay2(GetEye(), GetFront(), 12); canPending = false; if(blockCursorDragging) { // check the starting point is not floating auto start = blockCursorDragPos; if(map->IsSolidWrapped(start.x-1, start.y, start.z) || map->IsSolidWrapped(start.x, start.y-1, start.z) || map->IsSolidWrapped(start.x, start.y, start.z-1) || map->IsSolidWrapped(start.x+1, start.y, start.z) || map->IsSolidWrapped(start.x, start.y+1, start.z) || map->IsSolidWrapped(start.x, start.y, start.z+1)) { // still okay }else{ // cannot build; floating if(listener && this == world->GetLocalPlayer()) { listener-> LocalPlayerBuildError(BuildFailureReason::InvalidPosition); } blockCursorDragging = false; } } if(result.hit && (result.hitBlock + result.normal).z < 62 && (!OverlapsWithOneBlock(result.hitBlock + result.normal)) && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f && !pendingPlaceBlock){ // Building is possible, and there's no delayed block placement. blockCursorActive = true; blockCursorPos = result.hitBlock + result.normal; }else if(pendingPlaceBlock){ // Delayed Block Placement: When player attempts to place a block while jumping and // placing block is currently impossible, building will be delayed until it becomes // possible, as long as player is airborne. if(airborne == false || blockStocks <= 0){ // player is no longer airborne, or doesn't have a block to place. pendingPlaceBlock = false; lastSingleBlockBuildSeqDone = true; if(blockStocks > 0) { // cannot build; invalid position. } }else if((!OverlapsWithOneBlock(pendingPlaceBlockPos)) && BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){ // now building became possible. SPAssert(this == world->GetLocalPlayer()); if(GetWorld()->GetListener()) GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate); pendingPlaceBlock = false; lastSingleBlockBuildSeqDone = true; // blockStocks--; decrease when created nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); } }else{ // Delayed Block Placement can be activated only when the only reason making placement // impossible is that block to be placed overlaps with the player's hitbox. canPending = result.hit && (result.hitBlock + result.normal).z < 62 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f; blockCursorActive = false; int dist = 11; for(; dist >= 1 && BoxDistanceToBlock(result.hitBlock + result.normal) > 3.f ; dist--) { result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); } for(; dist < 12 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f ; dist++) { result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); } blockCursorPos = result.hitBlock + result.normal; } }else if(tool == ToolWeapon){ }else if(tool == ToolGrenade){ if(holdingGrenade){ if(world->GetTime() - grenadeTime > 2.9f){ ThrowGrenade(); } } } if(tool != ToolWeapon) weapon->SetShooting(false); if(weapon->FrameNext(dt)){ FireWeapon(); } if(weapon->IsReloading()) { lastReloadingTime = world->GetTime(); }else if(reloadingServerSide) { // for some reason a server didn't return // WeaponReload packet. if(world->GetTime() + lastReloadingTime + .8f) { reloadingServerSide = false; weapon->ForceReloadDone(); } } }
/* ================ ClientEvents Events will be passed on to the clients for presentation, but any server game effects are handled here ================ */ void ClientEvents(gentity_t * ent, int oldEventSequence) { int i, j; int event; gclient_t *client; int damage; // vec3_t dir; vec3_t origin, angles; gitem_t *item; gentity_t *drop; client = ent->client; if (oldEventSequence < client->ps.eventSequence - MAX_PS_EVENTS) { oldEventSequence = client->ps.eventSequence - MAX_PS_EVENTS; } for (i = oldEventSequence; i < client->ps.eventSequence; i++) { event = client->ps.events[i & (MAX_PS_EVENTS - 1)]; switch (event) { case EV_FALL_MEDIUM: case EV_FALL_FAR: if (ent->s.eType != ET_PLAYER) { break; // not in the player model } if (g_dmflags.integer & DF_NO_FALLING) { break; } // JBravo: fix falling pain during lca if (g_gametype.integer >= GT_TEAM && level.lights_camera_action) { break; } damage = ent->client->ps.stats[STAT_FALLDAMAGE]; // VectorSet(dir, 0, 0, 1); ent->pain_debounce_time = level.time + 200; // no normal pain sound //Elder: added so we can trigger AQ2 pain blends ent->client->ps.damageEvent++; ent->client->ps.damageCount += damage; if (ent->client->lasthurt_mod != 0) { //Blaze: Print out some debug info if (&g_entities[ent->client->lasthurt_client] == NULL) G_Printf("Ln 0748\n"); G_Damage(ent, &g_entities[ent->client->lasthurt_client], &g_entities[ent->client->lasthurt_client], NULL, NULL, damage, 0, MOD_FALLING); } else { G_Damage(ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING); } break; case EV_FALL_FAR_NOSOUND: if (ent->s.eType != ET_PLAYER) { break; // not in the player model } if (g_dmflags.integer & DF_NO_FALLING) { break; } // JBravo: fix falling pain during lca again if (g_gametype.integer >= GT_TEAM && level.lights_camera_action) { break; } damage = ent->client->ps.stats[STAT_FALLDAMAGE]; // VectorSet(dir, 0, 0, 1); ent->pain_debounce_time = level.time + 200; // no normal pain sound //Elder: added so we can trigger AQ2 pain blends ent->client->ps.damageEvent++; ent->client->ps.damageCount += damage; if (ent->client->lasthurt_mod != 0) { //Blaze: Print out some debug info if (&g_entities[ent->client->lasthurt_client] == NULL) G_Printf("Ln 0779\n"); G_Damage(ent, &g_entities[ent->client->lasthurt_client], &g_entities[ent->client->lasthurt_client], NULL, NULL, damage, 0, MOD_FALLING); } else { G_Damage(ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING); } break; case EV_FIRE_WEAPON: FireWeapon(ent); break; case EV_RELOAD_WEAPON1: ReloadWeapon(ent, 1); break; case EV_RELOAD_WEAPON2: ReloadWeapon(ent, 2); break; case EV_CHANGE_WEAPON: //Elder: not a good place to put stuff break; case EV_USE_ITEM1: // teleporter // drop flags in CTF item = NULL; j = 0; if (ent->client->ps.powerups[PW_REDFLAG]) { item = BG_FindItemForPowerup(PW_REDFLAG); j = PW_REDFLAG; } else if (ent->client->ps.powerups[PW_BLUEFLAG]) { item = BG_FindItemForPowerup(PW_BLUEFLAG); j = PW_BLUEFLAG; } else if (ent->client->ps.powerups[PW_NEUTRALFLAG]) { item = BG_FindItemForPowerup(PW_NEUTRALFLAG); j = PW_NEUTRALFLAG; } if (item) { drop = Drop_Item(ent, item, 0); // decide how many seconds it has left drop->count = (ent->client->ps.powerups[j] - level.time) / 1000; if (drop->count < 1) { drop->count = 1; } ent->client->ps.powerups[j] = 0; } SelectSpawnPoint(ent->client->ps.origin, origin, angles); TeleportPlayer(ent, origin, angles); break; case EV_USE_ITEM2: // medkit ent->health = 125; //ent->client->ps.stats[STAT_MAX_HEALTH] + 25; break; default: break; } } }
void Player::Update(float dt) { SPADES_MARK_FUNCTION(); MovePlayer(dt); if(tool == ToolSpade){ if(weapInput.primary){ if(world->GetTime() > nextSpadeTime){ UseSpade(); nextSpadeTime = world->GetTime() + GetToolPrimaryDelay(); } }else if(weapInput.secondary){ if(world->GetTime() > nextDigTime){ DigWithSpade(); nextDigTime = world->GetTime() + GetToolSecondaryDelay(); firstDig = false; } } }else if(tool == ToolBlock){ GameMap::RayCastResult result; result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), 12); canPending = false; if(result.hit && (result.hitBlock + result.normal).z < 62 && (!OverlapsWithOneBlock(result.hitBlock + result.normal)) && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f && !pendingPlaceBlock){ blockCursorActive = true; blockCursorPos = result.hitBlock + result.normal; }else if(pendingPlaceBlock){ if(airborne == false || blockStocks <= 0){ pendingPlaceBlock = false; }else if((!OverlapsWithOneBlock(pendingPlaceBlockPos)) && BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){ SPAssert(this == world->GetLocalPlayer()); if(GetWorld()->GetListener()) GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate); pendingPlaceBlock = false; // blockStocks--; decrease when created nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); } }else{ canPending = result.hit && (result.hitBlock + result.normal).z < 62 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f; blockCursorActive = false; blockCursorPos = result.hitBlock + result.normal; } }else if(tool == ToolWeapon){ }else if(tool == ToolGrenade){ if(holdingGrenade){ if(world->GetTime() - grenadeTime > 2.9f){ ThrowGrenade(); } } } if(tool != ToolWeapon) weapon->SetShooting(false); if(weapon->FrameNext(dt)){ FireWeapon(); } if(weapon->IsReloading()) { lastReloadingTime = world->GetTime(); }else if(reloadingServerSide) { // for some reason a server didn't return // WeaponReload packet. if(world->GetTime() + lastReloadingTime + .8f) { reloadingServerSide = false; weapon->ForceReloadDone(); } } }
/* ================ ClientEvents Events will be passed on to the clients for presentation, but any server game effects are handled here ================ */ void ClientEvents( gentity_t *ent, int oldEventSequence ) { int i; int event; gclient_t *client; int damage; vec3_t dir; client = ent->client; if ( oldEventSequence < client->ps.eventSequence - MAX_EVENTS ) { oldEventSequence = client->ps.eventSequence - MAX_EVENTS; } for ( i = oldEventSequence ; i < client->ps.eventSequence ; i++ ) { event = client->ps.events[ i & ( MAX_EVENTS - 1 ) ]; switch ( event ) { case EV_FALL_NDIE: //case EV_FALL_SHORT: case EV_FALL_DMG_10: case EV_FALL_DMG_15: case EV_FALL_DMG_25: //case EV_FALL_DMG_30: case EV_FALL_DMG_50: //case EV_FALL_DMG_75: if ( ent->s.eType != ET_PLAYER ) { break; // not in the player model } if ( g_dmflags.integer & DF_NO_FALLING ) { break; } if ( event == EV_FALL_NDIE ) { damage = 9999; } else if ( event == EV_FALL_DMG_50 ) { damage = 50; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; VectorClear( ent->client->ps.velocity ); } else if ( event == EV_FALL_DMG_25 ) { damage = 25; ent->client->ps.pm_time = 250; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; VectorClear( ent->client->ps.velocity ); } else if ( event == EV_FALL_DMG_15 ) { damage = 15; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; VectorClear( ent->client->ps.velocity ); } else if ( event == EV_FALL_DMG_10 ) { damage = 10; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; VectorClear( ent->client->ps.velocity ); } else { damage = 5; // never used } VectorSet( dir, 0, 0, 1 ); ent->pain_debounce_time = level.time + 200; // no normal pain sound G_Damage( ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING ); break; // JPW NERVE case EV_TESTID1: case EV_TESTID2: case EV_ENDTEST: break; // jpw case EV_FIRE_WEAPON_MG42: mg42_fire( ent ); break; case EV_FIRE_WEAPON: case EV_FIRE_WEAPONB: case EV_FIRE_WEAPON_LASTSHOT: FireWeapon( ent ); break; //----(SA) modified case EV_USE_ITEM1: // ( HI_MEDKIT ) medkit case EV_USE_ITEM2: // ( HI_WINE ) wine case EV_USE_ITEM3: // ( HI_SKULL ) skull of invulnerable case EV_USE_ITEM4: // ( HI_WATER ) protection from drowning case EV_USE_ITEM5: // ( HI_ELECTRIC ) protection from electric attacks case EV_USE_ITEM6: // ( HI_FIRE ) protection from fire attacks case EV_USE_ITEM7: // ( HI_STAMINA ) restores fatigue bar and sets "nofatigue" for a time period case EV_USE_ITEM8: // ( HI_BOOK1 ) case EV_USE_ITEM9: // ( HI_BOOK2 ) case EV_USE_ITEM10: // ( HI_BOOK3 ) UseHoldableItem( ent, event - EV_USE_ITEM0 ); break; //----(SA) end default: break; } } }
void ASWeapon::HandleFiring() { if (CurrentAmmoInClip > 0 && CanFire()) { if (GetNetMode() != NM_DedicatedServer) { SimulateWeaponFire(); } if (MyPawn && MyPawn->IsLocallyControlled()) { FireWeapon(); UseAmmo(); // Update firing FX on remote clients if this is called on server BurstCounter++; } } else if (CanReload()) { StartReload(); } else if (MyPawn && MyPawn->IsLocallyControlled()) { if (GetCurrentAmmo() == 0 && !bRefiring) { PlayWeaponSound(OutOfAmmoSound); } /* Reload after firing last round */ if (CurrentAmmoInClip <= 0 && CanReload()) { StartReload(); } /* Stop weapon fire FX, but stay in firing state */ if (BurstCounter > 0) { OnBurstFinished(); } } if (MyPawn && MyPawn->IsLocallyControlled()) { if (Role < ROLE_Authority) { ServerHandleFiring(); } /* Retrigger HandleFiring on a delay for automatic weapons */ bRefiring = (CurrentState == EWeaponState::Firing && TimeBetweenShots > 0.0f); if (bRefiring) { GetWorldTimerManager().SetTimer(TimerHandle_HandleFiring, this, &ASWeapon::HandleFiring, TimeBetweenShots, false); } } /* Make Noise on every shot. The data is managed by the PawnNoiseEmitterComponent created in SBaseCharacter and used by PawnSensingComponent in SZombieCharacter */ if (MyPawn) { MyPawn->MakePawnNoise(1.0f); } LastFireTime = GetWorld()->GetTimeSeconds(); }
void Ship::StaticUpdate(const float timeStep) { AITimeStep(timeStep); // moved to correct place, maybe if (GetHullTemperature() > 1.0) { Space::KillBody(this); } UpdateAlertState(); /* FUEL SCOOPING!!!!!!!!! */ if (m_equipment.Get(Equip::SLOT_FUELSCOOP) != Equip::NONE) { Body *astro = GetFrame()->m_astroBody; if (astro && astro->IsType(Object::PLANET)) { Planet *p = static_cast<Planet*>(astro); if (p->IsSuperType(SBody::SUPERTYPE_GAS_GIANT)) { double dist = GetPosition().Length(); double pressure, density; p->GetAtmosphericState(dist, &pressure, &density); double speed = GetVelocity().Length(); vector3d vdir = GetVelocity().Normalized(); matrix4x4d rot; GetRotMatrix(rot); vector3d pdir = -vector3d(rot[8], rot[9], rot[10]).Normalized(); double dot = vdir.Dot(pdir); if ((m_stats.free_capacity) && (dot > 0.95) && (speed > 2000.0) && (density > 1.0)) { double rate = speed*density*0.00001f; if (Pi::rng.Double() < rate) { m_equipment.Add(Equip::HYDROGEN); if (this == reinterpret_cast<Ship*>(Pi::player)) { Pi::Message(stringf(Lang::FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED, formatarg("quantity", m_equipment.Count(Equip::SLOT_CARGO, Equip::HYDROGEN)))); } UpdateMass(); } } } } } // Cargo bay life support if (m_equipment.Get(Equip::SLOT_CARGOLIFESUPPORT) != Equip::CARGO_LIFE_SUPPORT) { // Hull is pressure-sealed, it just doesn't provide // temperature regulation and breathable atmosphere // kill stuff roughly every 5 seconds if ((!m_dockedWith) && (5.0*Pi::rng.Double() < timeStep)) { Equip::Type t = (Pi::rng.Int32(2) ? Equip::LIVE_ANIMALS : Equip::SLAVES); if (m_equipment.Remove(t, 1)) { m_equipment.Add(Equip::FERTILIZER); if (this == reinterpret_cast<Ship*>(Pi::player)) { Pi::Message(Lang::CARGO_BAY_LIFE_SUPPORT_LOST); } } } } if (m_flightState == FLYING) m_launchLockTimeout -= timeStep; if (m_launchLockTimeout < 0) m_launchLockTimeout = 0; /* can't orient ships in SetDockedWith() because it gets * called from collision handler, and collision system gets a bit * weirded out if bodies are moved in the middle of collision detection */ if (m_dockedWith) m_dockedWith->OrientDockedShip(this, m_dockedWithPort); // lasers for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) { m_gunRecharge[i] -= timeStep; float rateCooling = 0.01f; if (m_equipment.Get(Equip::SLOT_LASERCOOLER) != Equip::NONE) { rateCooling *= float(EquipType::types[ m_equipment.Get(Equip::SLOT_LASERCOOLER) ].pval); } m_gunTemperature[i] -= rateCooling*timeStep; if (m_gunTemperature[i] < 0.0f) m_gunTemperature[i] = 0; if (m_gunRecharge[i] < 0.0f) m_gunRecharge[i] = 0; if (!m_gunState[i]) continue; if (m_gunRecharge[i] > 0.0f) continue; if (m_gunTemperature[i] > 1.0) continue; FireWeapon(i); } if (m_ecmRecharge > 0.0f) { m_ecmRecharge = std::max(0.0f, m_ecmRecharge - timeStep); } if (m_stats.shield_mass_left < m_stats.shield_mass) { // 250 second recharge float recharge_rate = 0.004f; if (m_equipment.Get(Equip::SLOT_ENERGYBOOSTER) != Equip::NONE) { recharge_rate *= float(EquipType::types[ m_equipment.Get(Equip::SLOT_ENERGYBOOSTER) ].pval); } m_stats.shield_mass_left += m_stats.shield_mass * recharge_rate * timeStep; } m_stats.shield_mass_left = Clamp(m_stats.shield_mass_left, 0.0f, m_stats.shield_mass); if (m_wheelTransition) { m_wheelState += m_wheelTransition*0.3f*timeStep; m_wheelState = Clamp(m_wheelState, 0.0f, 1.0f); if (float_equal_exact(m_wheelState, 0.0f) || float_equal_exact(m_wheelState, 1.0f)) m_wheelTransition = 0; } if (m_testLanded) TestLanded(); if (m_equipment.Get(Equip::SLOT_HULLAUTOREPAIR) == Equip::HULL_AUTOREPAIR) { const ShipType &stype = GetShipType(); m_stats.hull_mass_left = std::min(m_stats.hull_mass_left + 0.1f*timeStep, float(stype.hullMass)); } // After calling StartHyperspaceTo this Ship must not spawn objects // holding references to it (eg missiles), as StartHyperspaceTo // removes the ship from Space::bodies and so the missile will not // have references to this cleared by NotifyDeleted() if (m_hyperspace.countdown > 0.0f) { m_hyperspace.countdown = m_hyperspace.countdown - timeStep; if (m_hyperspace.countdown <= 0.0f) { m_hyperspace.countdown = 0; m_hyperspace.now = true; } } if (m_hyperspace.now) { m_hyperspace.now = false; Space::StartHyperspaceTo(this, &m_hyperspace.dest); } }
/* ================ ClientEvents Events will be passed on to the clients for presentation, but any server game effects are handled here ================ */ void ClientEvents(gentity_t *ent, int oldEventSequence) { int i; gclient_t *client; int damage; client = ent->client; if (oldEventSequence < client->ps.eventSequence - MAX_EVENTS) { oldEventSequence = client->ps.eventSequence - MAX_EVENTS; } for (i = oldEventSequence ; i < client->ps.eventSequence ; ++i) { int event = client->ps.events[i & (MAX_EVENTS - 1)]; switch (event) { case EV_FALL_NDIE: case EV_FALL_DMG_10: case EV_FALL_DMG_15: case EV_FALL_DMG_25: case EV_FALL_DMG_50: // rain - VectorClear() used to be done here whenever falling // damage occured, but I moved it to bg_pmove where it belongs. if (ent->s.eType != ET_PLAYER) { break; // not in the player model } if (event == EV_FALL_NDIE) { damage = 9999; } else if (event == EV_FALL_DMG_50) { damage = 50; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } else if (event == EV_FALL_DMG_25) { damage = 25; ent->client->ps.pm_time = 250; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } else if (event == EV_FALL_DMG_15) { damage = 15; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } else if (event == EV_FALL_DMG_10) { damage = 10; ent->client->ps.pm_time = 1000; ent->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } else { damage = 5; // never used } ent->pain_debounce_time = level.time + 200; // no normal pain sound G_Damage(ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING); break; case EV_FIRE_WEAPON_MG42: mg42_fire(ent); break; case EV_FIRE_WEAPON_MOUNTEDMG42: mountedmg42_fire(ent); break; case EV_FIRE_WEAPON_AAGUN: aagun_fire(ent); break; case EV_FIRE_WEAPON: case EV_FIRE_WEAPONB: case EV_FIRE_WEAPON_LASTSHOT: FireWeapon(ent); break; default: break; } } }
void Ship::StaticUpdate(const float timeStep) { // do player sounds before dead check, so they also turn off if (IsType(Object::PLAYER)) DoThrusterSounds(); if (IsDead()) return; if (m_controller) m_controller->StaticUpdate(timeStep); if (GetHullTemperature() > 1.0) Explode(); UpdateAlertState(); /* FUEL SCOOPING!!!!!!!!! */ int capacity = 0; Properties().Get("fuel_scoop_cap", capacity); if (m_flightState == FLYING && capacity > 0) { Body *astro = GetFrame()->GetBody(); if (astro && astro->IsType(Object::PLANET)) { Planet *p = static_cast<Planet*>(astro); if (p->GetSystemBody()->IsScoopable()) { double dist = GetPosition().Length(); double pressure, density; p->GetAtmosphericState(dist, &pressure, &density); double speed = GetVelocity().Length(); vector3d vdir = GetVelocity().Normalized(); vector3d pdir = -GetOrient().VectorZ(); double dot = vdir.Dot(pdir); if ((m_stats.free_capacity) && (dot > 0.95) && (speed > 2000.0) && (density > 1.0)) { double rate = speed*density*0.00000333f*double(capacity); if (Pi::rng.Double() < rate) { lua_State *l = Lua::manager->GetLuaState(); pi_lua_import(l, "Equipment"); LuaTable hydrogen = LuaTable(l, -1).Sub("cargo").Sub("hydrogen"); LuaObject<Ship>::CallMethod(this, "AddEquip", hydrogen); UpdateEquipStats(); if (this->IsType(Object::PLAYER)) { Pi::game->log->Add(stringf(Lang::FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED, formatarg("quantity", LuaObject<Ship>::CallMethod<int>(this, "CountEquip", hydrogen)))); } lua_pop(l, 3); } } } } } // Cargo bay life support capacity = 0; Properties().Get("cargo_life_support_cap", capacity); if (!capacity) { // Hull is pressure-sealed, it just doesn't provide // temperature regulation and breathable atmosphere // kill stuff roughly every 5 seconds if ((!m_dockedWith) && (5.0*Pi::rng.Double() < timeStep)) { std::string t(Pi::rng.Int32(2) ? "live_animals" : "slaves"); lua_State *l = Lua::manager->GetLuaState(); pi_lua_import(l, "Equipment"); LuaTable cargo = LuaTable(l, -1).Sub("cargo"); if (LuaObject<Ship>::CallMethod<int>(this, "RemoveEquip", cargo.Sub(t))) { LuaObject<Ship>::CallMethod<int>(this, "AddEquip", cargo.Sub("fertilizer")); if (this->IsType(Object::PLAYER)) { Pi::game->log->Add(Lang::CARGO_BAY_LIFE_SUPPORT_LOST); } lua_pop(l, 4); } else lua_pop(l, 3); } } if (m_flightState == FLYING) m_launchLockTimeout -= timeStep; if (m_launchLockTimeout < 0) m_launchLockTimeout = 0; if (m_flightState == JUMPING || m_flightState == HYPERSPACE) m_launchLockTimeout = 0; // lasers for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) { m_gun[i].recharge -= timeStep; float rateCooling = 0.01f; float cooler = 1.0f; Properties().Get("laser_cooler_cap", cooler); rateCooling *= cooler; m_gun[i].temperature -= rateCooling*timeStep; if (m_gun[i].temperature < 0.0f) m_gun[i].temperature = 0; if (m_gun[i].recharge < 0.0f) m_gun[i].recharge = 0; if (!m_gun[i].state) continue; if (m_gun[i].recharge > 0.0f) continue; if (m_gun[i].temperature > 1.0) continue; FireWeapon(i); } if (m_ecmRecharge > 0.0f) { m_ecmRecharge = std::max(0.0f, m_ecmRecharge - timeStep); } if (m_shieldCooldown > 0.0f) { m_shieldCooldown = std::max(0.0f, m_shieldCooldown - timeStep); } if (m_stats.shield_mass_left < m_stats.shield_mass) { // 250 second recharge float recharge_rate = 0.004f; float booster = 1.0f; Properties().Get("shield_energy_booster_cap", booster); recharge_rate *= booster; m_stats.shield_mass_left = Clamp(m_stats.shield_mass_left + m_stats.shield_mass * recharge_rate * timeStep, 0.0f, m_stats.shield_mass); Properties().Set("shieldMassLeft", m_stats.shield_mass_left); } if (m_wheelTransition) { m_wheelState += m_wheelTransition*0.3f*timeStep; m_wheelState = Clamp(m_wheelState, 0.0f, 1.0f); if (is_equal_exact(m_wheelState, 0.0f) || is_equal_exact(m_wheelState, 1.0f)) m_wheelTransition = 0; } if (m_testLanded) TestLanded(); capacity = 0; Properties().Get("hull_autorepair_cap", capacity); if (capacity) { m_stats.hull_mass_left = std::min(m_stats.hull_mass_left + 0.1f*timeStep, float(m_type->hullMass)); Properties().Set("hullMassLeft", m_stats.hull_mass_left); Properties().Set("hullPercent", 100.0f * (m_stats.hull_mass_left / float(m_type->hullMass))); } // After calling StartHyperspaceTo this Ship must not spawn objects // holding references to it (eg missiles), as StartHyperspaceTo // removes the ship from Space::bodies and so the missile will not // have references to this cleared by NotifyRemoved() if (m_hyperspace.now) { m_hyperspace.now = false; EnterHyperspace(); } if (m_hyperspace.countdown > 0.0f) { // Check the Lua function bool abort = false; lua_State * l = m_hyperspace.checks.GetLua(); if (l) { m_hyperspace.checks.PushCopyToStack(); if (lua_isfunction(l, -1)) { lua_call(l, 0, 1); abort = !lua_toboolean(l, -1); lua_pop(l, 1); } } if (abort) { AbortHyperjump(); } else { m_hyperspace.countdown = m_hyperspace.countdown - timeStep; if (!abort && m_hyperspace.countdown <= 0.0f) { m_hyperspace.countdown = 0; m_hyperspace.now = true; SetFlightState(JUMPING); // We have to fire it here, because the event isn't actually fired until // after the whole physics update, which means the flight state on next // step would be HYPERSPACE, thus breaking quite a few things. LuaEvent::Queue("onLeaveSystem", this); } } } //Add smoke trails for missiles on thruster state static double s_timeAccum = 0.0; s_timeAccum += timeStep; if (m_type->tag == ShipType::TAG_MISSILE && !is_equal_exact(m_thrusters.LengthSqr(), 0.0) && (s_timeAccum > 4 || 0.1*Pi::rng.Double() < timeStep)) { s_timeAccum = 0.0; const vector3d pos = GetOrient() * vector3d(0, 0 , 5); const float speed = std::min(10.0*GetVelocity().Length()*std::max(1.0,fabs(m_thrusters.z)),100.0); SfxManager::AddThrustSmoke(this, speed, pos); } }
/* ================ ClientEvents Events will be passed on to the clients for presentation, but any server game effects are handled here ================ */ void ClientEvents( gentity_t *ent, int oldEventSequence ) { int i;//, j; int event; gclient_t *client; int damage; vec3_t dir; // vec3_t origin, angles; // qboolean fired; // gitem_t *item; // gentity_t *drop; client = ent->client; if ( oldEventSequence < client->ps.eventSequence - MAX_PS_EVENTS ) { oldEventSequence = client->ps.eventSequence - MAX_PS_EVENTS; } for ( i = oldEventSequence ; i < client->ps.eventSequence ; i++ ) { event = client->ps.events[ i & (MAX_PS_EVENTS-1) ]; switch ( event ) { case EV_FALL: case EV_ROLL: { int delta = client->ps.eventParms[ i & (MAX_PS_EVENTS-1) ]; if (ent->client && ent->client->ps.fallingToDeath) { break; } if ( ent->s.eType != ET_PLAYER ) { break; // not in the player model } if ( g_dmflags.integer & DF_NO_FALLING ) { break; } if (delta <= 44) { break; } damage = delta*0.16; //good enough for now, I guess VectorSet (dir, 0, 0, 1); ent->pain_debounce_time = level.time + 200; // no normal pain sound G_Damage (ent, NULL, NULL, NULL, NULL, damage, DAMAGE_NO_ARMOR, MOD_FALLING); } break; case EV_FIRE_WEAPON: FireWeapon( ent, qfalse ); ent->client->dangerTime = level.time; ent->client->ps.eFlags &= ~EF_INVULNERABLE; ent->client->invulnerableTimer = 0; break; case EV_ALT_FIRE: FireWeapon( ent, qtrue ); ent->client->dangerTime = level.time; ent->client->ps.eFlags &= ~EF_INVULNERABLE; ent->client->invulnerableTimer = 0; break; case EV_SABER_ATTACK: ent->client->dangerTime = level.time; ent->client->ps.eFlags &= ~EF_INVULNERABLE; ent->client->invulnerableTimer = 0; break; //rww - Note that these must be in the same order (ITEM#-wise) as they are in holdable_t case EV_USE_ITEM1: //seeker droid ItemUse_Seeker(ent); break; case EV_USE_ITEM2: //shield ItemUse_Shield(ent); break; case EV_USE_ITEM3: //medpack ItemUse_MedPack(ent); break; case EV_USE_ITEM4: //datapad //G_Printf("Used Datapad\n"); break; case EV_USE_ITEM5: //binoculars ItemUse_Binoculars(ent); break; case EV_USE_ITEM6: //sentry gun ItemUse_Sentry(ent); break; default: break; } } }