void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc) { ProjectileContainer::iterator pci; for (pci = pc.begin(); pci != pc.end(); ++pci) { CProjectile* p = *pci; if (!p->checkCol) { continue; } // NOTE: if <p> is a MissileProjectile and does not // have selfExplode set, it will never be removed (!) if (p->GetCollisionFlags() & Collision::NOGROUND) { continue; } // NOTE: don't add p->radius to groundHeight, or most // projectiles will collide with the ground too early const float groundHeight = ground->GetHeightReal(p->pos.x, p->pos.z); const bool belowGround = (p->pos.y < groundHeight); const bool insideWater = (p->pos.y <= 0.0f && !belowGround); const bool ignoreWater = p->ignoreWater; if (belowGround || (insideWater && !ignoreWater)) { // if position has dropped below terrain or into water // where we cannot live, adjust it and explode us now // (if the projectile does not set deleteMe = true, it // will keep hugging the terrain) p->pos.y = belowGround? groundHeight: 0.0f; p->Collision(); } } }
void CJaw::OnShoot(EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3 &vel) { BaseClass::OnShoot(shooterId, ammoId, pAmmoType, pos, dir, vel); CActor *pOwnerActor = GetOwnerActor(); if (pOwnerActor) { // Set the projectile to target the forced entity if (m_forcedTargetId > 0) { CProjectile *pProjectile = g_pGame->GetWeaponSystem()->GetProjectile(ammoId); if (pProjectile) { pProjectile->SetDestination(m_forcedTargetId); } } if (pOwnerActor->IsClient() && m_laserGuider.IsLaserActivated()) { SHUDEvent event(eHUDEvent_InfoSystemsEvent); event.AddData(SHUDEventData(1)); event.AddData(SHUDEventData(2.f)); event.AddData(SHUDEventData("@hud_guided")); CHUDEventDispatcher::CallEvent(event); } if (pOwnerActor->IsClient()) m_fired = true; } SvActivateMissileCountermeasures(shooterId, pos, dir); }
void CCustomExplosionGenerator::Explosion(const float3 &pos, const DamageArray& damages, float radius, CUnit *owner,float gfxMod, CUnit *hit) { float h2=ground->GetHeight2(pos.x,pos.z); unsigned int flags = 0; if (h2<-3) flags = SPW_WATER; else if (pos.y<-15) flags = SPW_UNDERWATER; else if (pos.y-max((float)0,h2)>20) flags = SPW_AIR; else flags = SPW_GROUND; if (hit) flags |= SPW_UNIT; else flags |= SPW_NO_UNIT; for (int a=0; a<projectileSpawn.size(); a++) { ProjectileSpawnInfo *psi = projectileSpawn[a]; if (!(psi->flags & flags)) continue; for (int c=0; c<psi->count; c++) { CProjectile *projectile = (CProjectile*)psi->projectileClass->CreateInstance (); ExecuteExplosionCode (&psi->code[0], damages.damages[0], (char*)projectile, c); projectile->Init(pos, owner); } } if ((flags & SPW_GROUND) && groundFlash) new CStandarGroundFlash(pos, groundFlash->circleAlpha, groundFlash->flashAlpha, groundFlash->flashSize, groundFlash->circleGrowth, groundFlash->ttl, groundFlash->color); if (useDefaultExplosions) CStdExplosionGenerator::Explosion(pos, damages, radius, owner, gfxMod, hit); }
int CLuaFile::ProjectileFind(lua_State *L) { lua_getglobal(L, "pLUA"); CLuaFile *pSelf = (CLuaFile *)lua_touserdata(L, -1); lua_Debug Frame; lua_getstack(L, 1, &Frame); lua_getinfo(L, "nlSf", &Frame); if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4)) return 0; vec2 Pos = vec2(lua_tonumber(L, 1), lua_tonumber(L, 2)); int Max = clamp((int)lua_tointeger(L, 4), 1, 256); int Num = 0; for (CProjectile *pPrj = (CProjectile *)pSelf->m_pServer->m_World.FindFirst(0); pPrj; pPrj = (CProjectile *)pPrj->TypeNext()) { if(distance(pPrj->GetPos((pSelf->m_pServer->Server()->Tick()-pPrj->GetStartTick())/(float)pSelf->m_pServer->Server()->TickSpeed()), Pos) < lua_tonumber(L, 3)+pPrj->m_ProximityRadius) { lua_pushinteger(L, pPrj->GetID()); Num++; if(Num == Max) break; } } return Num; }
//------------------------------------------------------------------------ CProjectile *CWeaponSystem::DoSpawnAmmo(IEntityClass *pAmmoType, bool isRemote, const SAmmoParams *pAmmoParams) { bool isServer=gEnv->bServer; bool isClient=gEnv->IsClient(); if(pAmmoParams->serverSpawn && (!isServer || IsDemoPlayback())) { if(!pAmmoParams->predictSpawn || isRemote) return 0; } SEntitySpawnParams spawnParams; spawnParams.pClass = pAmmoType; spawnParams.sName = "ammo"; spawnParams.nFlags = pAmmoParams->flags | ENTITY_FLAG_NO_PROXIMITY; // No proximity for this entity. IEntity *pEntity = gEnv->pEntitySystem->SpawnEntity(spawnParams); if(!pEntity) { GameWarning("Failed to spawn ammo '%s'! Entity creation failed...", pAmmoType->GetName()); return 0; } CProjectile *pProjectile = GetProjectile(pEntity->GetId()); if(pProjectile && !isServer && !isRemote && pAmmoParams->predictSpawn) pProjectile->GetGameObject()->RegisterAsPredicted(); return pProjectile; }
void CDeflectorShield::ShootDeflectedEnergy(const CDeflectorShield::SDeflectedEnergy& energy) { if (!m_pAmmoClass) return; CProjectile* pEnergyBlast = g_pGame->GetWeaponSystem()->SpawnAmmo(m_pAmmoClass, false); if (!pEnergyBlast) return; const Matrix34& worldTransform = GetEntity()->GetWorldTM(); const float positionBias = 0.05f; const Vec3 worldReflectPos = worldTransform.TransformPoint(energy.m_localPosition); const Vec3 worldReflectDir = worldTransform.TransformVector(energy.m_localDirection); const Vec3 worldSpreadU = worldReflectDir.GetOrthogonal(); const Vec3 worldSpreadV = worldReflectDir.Cross(worldSpreadU); const float spreadOffset = cry_random(0.0f, m_spread); const Vec3 position = worldReflectPos + worldReflectDir * positionBias; Vec3 direction = worldReflectDir + (worldSpreadU * cry_random(0.0f, m_spread)) + (worldSpreadV * cry_random(0.0f, m_spread)); direction.Normalize(); CProjectile::SProjectileDesc projectileDesc( 0, 0, 0, energy.m_damage, m_dropMinDistance, m_dropPerMeter, float(m_minDamage), m_hitTypeId, 0, false); pEnergyBlast->SetParams(projectileDesc); pEnergyBlast->Launch(position, direction, Vec3(ZERO)); }
//----------------------------------------------------------------------------- // Прорисовываем все объекты //----------------------------------------------------------------------------- void DrawAllProjectile(bool VertexOnlyPass, unsigned int ShadowMap) { CProjectile *tmp = StartProjectile; while (tmp!=0) { CProjectile *tmp2 = tmp->Next; tmp->Draw(VertexOnlyPass, ShadowMap); tmp = tmp2; } }
int CLuaFile::ProjectileCreate(lua_State *L) { lua_getglobal(L, "pLUA"); CLuaFile *pSelf = (CLuaFile *)lua_touserdata(L, -1); lua_Debug Frame; lua_getstack(L, 1, &Frame); lua_getinfo(L, "nlSf", &Frame); if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) return 0; int ID = -1; vec2 Dir = vec2(0, -1); int Lifespan = 50; int Type = WEAPON_GUN; int Damage = 1; float Force = 0; bool Explosive = false; int ImpactSound = -1; if (lua_isnumber(L, 3) && lua_isnumber(L, 4)) Dir = vec2(lua_tonumber(L, 3), lua_tonumber(L, 4)); if (lua_isnumber(L, 5)) ID = lua_tointeger(L, 5); if (lua_isnumber(L, 6)) Lifespan = lua_tointeger(L, 6); if (lua_isnumber(L, 7)) Type = lua_tointeger(L, 7); if (lua_isnumber(L, 8)) Damage = lua_tointeger(L, 8); if (lua_isnumber(L, 9)) Force = lua_tonumber(L, 9); if (lua_isboolean(L, 10)) Explosive = lua_toboolean(L, 10); if (lua_isnumber(L, 11)) ImpactSound = lua_tonumber(L, 11); int Weapon = Type; if (lua_isnumber(L, 7)) Weapon = lua_tointeger(L, 7); CProjectile *pProj = new CProjectile(&pSelf->m_pServer->m_World, Type, ID, vec2(lua_tonumber(L, 1), lua_tonumber(L, 2)), Dir, Lifespan, Damage, Explosive, Force, ImpactSound, Weapon); CNetObj_Projectile p; pProj->FillInfo(&p); return 0; }
//----------------------------------------------------------------------------- // Проверяем все объекты, обновляем данные //----------------------------------------------------------------------------- void UpdateAllProjectile(float Time) { CProjectile *tmp = StartProjectile; while (tmp!=0) { CProjectile *tmp2 = tmp->Next; // делаем обновление данных по объекту if (!tmp->Update(Time)) { // если его нужно уничтожить - делаем это delete tmp; tmp = 0; } tmp = tmp2; } }
void CGround::CheckCol(CProjectileHandler* ph) { Projectile_List::iterator psi; for (psi = ph->ps.begin(); psi != ph->ps.end(); ++psi) { CProjectile* p = *psi; if (p->checkCol) { if (GetHeight(p->pos.x, p->pos.z) > p->pos.y /* - p->radius*/) { // too many projectiles seem to hit the ground before hitting // so remove the radius till a better fix is done p->Collision(); } } } }
void CProjectileHandler::DrawProjectilesShadow(const ProjectileContainer& pc) { for (ProjectileContainer::render_iterator pci = pc.render_begin(); pci != pc.render_end(); ++pci) { CProjectile* p = *pci; if ((gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam) || (p->owner() && teamHandler->Ally(p->owner()->allyteam, gu->myAllyTeam)))) { if (p->s3domodel) { p->DrawUnitPart(); } else if (p->castShadow) { p->Draw(); } } } }
void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc) { ProjectileContainer::iterator pci; for (pci = pc.begin(); pci != pc.end(); ++pci) { CProjectile* p = *pci; if (p->checkCol) { // too many projectiles seem to impact the ground before // actually hitting so don't subtract the projectile radius if (ground->GetHeight(p->pos.x, p->pos.z) > p->pos.y /* - p->radius*/) { p->Collision(); } } } }
//------------------------------------------------------------------------ CProjectile *CWeaponSystem::SpawnAmmo(IEntityClass* pAmmoType, bool isRemote) { TAmmoTypeParams::const_iterator it = m_ammoparams.find(pAmmoType); if (it == m_ammoparams.end()) { GameWarning("Failed to spawn ammo '%s'! Unknown class or entity class not registered...", pAmmoType?pAmmoType->GetName():""); return 0; } const SAmmoParams* pAmmoParams = it->second.params; if (!m_config.empty()) { std::map<string, const SAmmoParams *>::const_iterator cit=it->second.configurations.find(m_config); if (cit != it->second.configurations.end()) pAmmoParams=cit->second; else pAmmoParams=it->second.params; } bool isServer=gEnv->bServer; bool isClient=gEnv->bClient; if ( pAmmoParams->serverSpawn && (!isServer || IsDemoPlayback()) ) { if (!pAmmoParams->predictSpawn || isRemote) return 0; } SEntitySpawnParams spawnParams; spawnParams.pClass = pAmmoType; spawnParams.sName = "ammo"; spawnParams.nFlags = pAmmoParams->flags | ENTITY_FLAG_NO_PROXIMITY; // No proximity for this entity. IEntity *pEntity = gEnv->pEntitySystem->SpawnEntity(spawnParams); if (!pEntity) { GameWarning("Failed to spawn ammo '%s'! Entity creation failed...", pAmmoType->GetName()); return 0; } CProjectile *pProjectile = GetProjectile(pEntity->GetId()); if (pProjectile && !isServer && !isRemote && pAmmoParams->predictSpawn) pProjectile->GetGameObject()->RegisterAsPredicted(); return pProjectile; }
CProjectile mod::makeProjectile(CGameWorld *pGameWorld, int Type, int Owner,CPlayer* sender,vec2 Pos, vec2 Dir, int Span, int Damage, bool Explosive, float Force, int SoundImpact, int Weapon, IServer* server) { CProjectile *pProj = new CProjectile(pGameWorld, Type, Owner, Pos, Dir, Span, Damage, Explosive, Force, SoundImpact, Weapon); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); server->SendMsg(&Msg, 0, sender->GetCID()); }
int CLuaFile::ProjectileGetSoundImpact(lua_State *L) { lua_getglobal(L, "pLUA"); CLuaFile *pSelf = (CLuaFile *)lua_touserdata(L, -1); lua_Debug Frame; lua_getstack(L, 1, &Frame); lua_getinfo(L, "nlSf", &Frame); if (!lua_isnumber(L, 1)) return 0; CProjectile *pPrj = (CProjectile *)pSelf->m_pServer->m_World.GetEntityByID(lua_tointeger(L, 1)); if (pPrj) { lua_pushinteger(L, pPrj->GetSoundImpact()); return 1; } return 0; }
//------------------------------------------------------------------------ bool CGunTurret::IsTACBullet(IEntity *pTarget) const { const static IEntityClass *pTacClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("tacprojectile"); const static IEntityClass *pTacGunClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("tacgunprojectile"); if(pTarget->GetClass() != pTacClass && pTarget->GetClass() != pTacGunClass) return false; CProjectile *p = g_pGame->GetWeaponSystem()->GetProjectile(pTarget->GetId()); if(!p) return false; IActor *pActor = GetActor(p->GetOwnerId()); if(!pActor || !IsTargetHostile(pActor)) return false; return true; }
int CLuaFile::ProjectileGetPos(lua_State *L) { lua_getglobal(L, "pLUA"); CLuaFile *pSelf = (CLuaFile *)lua_touserdata(L, -1); lua_Debug Frame; lua_getstack(L, 1, &Frame); lua_getinfo(L, "nlSf", &Frame); if (!lua_isnumber(L, 1)) return 0; CProjectile *pPrj = (CProjectile *)pSelf->m_pServer->m_World.GetEntityByID(lua_tointeger(L, 1)); if (pPrj) { vec2 Pos = pPrj->GetPos((pSelf->m_pServer->Server()->Tick()-pPrj->GetStartTick())/(float)pSelf->m_pServer->Server()->TickSpeed()); lua_pushnumber(L, Pos.x); lua_pushnumber(L, Pos.y); return 2; } return 0; }
void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc) { for (size_t i = 0; i < pc.size(); ++i) { CProjectile* p = pc[i]; if (!p->checkCol) continue; // NOTE: // if <p> is a MissileProjectile and does not have // selfExplode set, tbis will cause it to never be // removed (!) if (p->GetCollisionFlags() & Collision::NOGROUND) continue; // don't collide with ground yet if last update scheduled a bounce if (p->weapon && static_cast<const CWeaponProjectile*>(p)->HasScheduledBounce()) continue; // NOTE: // don't add p->radius to groundHeight, or most (esp. modelled) // projectiles will collide with the ground one or more frames // too early const float groundHeight = CGround::GetHeightReal(p->pos.x, p->pos.z); const bool belowGround = (p->pos.y < groundHeight); const bool insideWater = (p->pos.y <= 0.0f && !belowGround); const bool ignoreWater = p->ignoreWater; if (belowGround || (insideWater && !ignoreWater)) { // if position has dropped below terrain or into water // where we can not live, adjust it and explode us now // (if the projectile does not set deleteMe = true, it // will keep hugging the terrain) p->SetPosition(p->pos * XZVector + UpVector * groundHeight * belowGround); p->Collision(); } } }
void CSingularity::Suck() { float Len; CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(!p || !p->IsAlive()) continue; Len = distance(m_Pos, p->m_Pos); if(Len < m_KillRange) { if(m_Owner > -1) p->Die(m_Owner,WEAPON_RIFLE); else p->Die(p->GetPlayer()->GetCID(),WEAPON_WORLD); } else if(Len < m_Range) p->SetVel(p->GetVel() + (normalize(m_Pos - p->m_Pos) * exp((m_Range - Len)/(m_Range/2.5f)))); } // save CPU for projectiles if(m_SkipTick) return; CProjectile *s = (CProjectile *)GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); for(; s; s = (CProjectile *)s->TypeNext()) { if(!s) continue; Len = distance(m_Pos, s->m_Pos); if(Len < m_Range*1.5) s->SetVel(s->GetVel() + ((normalize(m_Pos - s->m_Pos) * exp((m_Range*1.5 - Len)/(m_Range*0.6f)))*0.04f)); } }
void CProjectileHandler::UpdateProjectileContainer(ProjectileContainer& pc, bool synced) { ProjectileContainer::iterator pci = pc.begin(); while (pci != pc.end()) { CProjectile* p = *pci; if (p->deleteMe) { if (p->synced) { assert(synced); if(p->weapon || p->piece) { //! iterator is always valid const ProjectileMap::iterator it = syncedProjectileIDs.find(p->id); const ProjectileMapPair& pp = it->second; eventHandler.ProjectileDestroyed(pp.first, pp.second); syncedProjectileIDs.erase(it); if (p->id != 0) { freeIDs.push_back(p->id); } } //! push_back this projectile for deletion pci = pc.erase_delete_synced(pci); } else { assert(!synced); pci = pc.erase_delete(pci); } } else { p->Update(); GML_GET_TICKS(p->lastProjUpdate); ++pci; } } }
void CProjectileHandler::DrawProjectilesMiniMap(const ProjectileContainer& pc) { if (pc.render_size() > 0) { CVertexArray* lines = GetVertexArray(); CVertexArray* points = GetVertexArray(); lines->Initialize(); lines->EnlargeArrays(pc.render_size() * 2, 0, VA_SIZE_C); points->Initialize(); points->EnlargeArrays(pc.render_size(), 0, VA_SIZE_C); for (ProjectileContainer::render_iterator pci = pc.render_begin(); pci != pc.render_end(); ++pci) { CProjectile* p = *pci; if ((p->owner() && (p->owner()->allyteam == gu->myAllyTeam)) || gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam)) { p->DrawOnMinimap(*lines, *points); } } lines->DrawArrayC(GL_LINES); points->DrawArrayC(GL_POINTS); } }
void CProjectileHandler::DrawProjectiles(const ProjectileContainer& pc, bool drawReflection, bool drawRefraction) { for (ProjectileContainer::render_iterator pci = pc.render_begin(); pci != pc.render_end(); ++pci) { CProjectile* pro = *pci; pro->UpdateDrawPos(); if (camera->InView(pro->pos, pro->drawRadius) && (gu->spectatingFullView || loshandler->InLos(pro, gu->myAllyTeam) || (pro->owner() && teamHandler->Ally(pro->owner()->allyteam, gu->myAllyTeam)))) { CUnit* owner = pro->owner(); bool stunned = owner? owner->stunned: false; if (owner && stunned && dynamic_cast<CShieldPartProjectile*>(pro)) { // if the unit that fired this projectile is stunned and the projectile // forms part of a shield (ie., the unit has a CPlasmaRepulser weapon but // cannot fire it), prevent the projectile (shield segment) from being drawn // // also prevents shields being drawn at unit's pre-pickup position // (since CPlasmaRepulser::Update() is responsible for updating // CShieldPartProjectile::centerPos) if the unit is in a non-fireplatform // transport continue; } if (drawReflection) { if (pro->pos.y < -pro->drawRadius) continue; float dif = pro->pos.y - camera->pos.y; float3 zeroPos = camera->pos * (pro->pos.y / dif) + pro->pos * (-camera->pos.y / dif); if (ground->GetApproximateHeight(zeroPos.x, zeroPos.z) > 3 + 0.5f * pro->drawRadius) continue; } if (drawRefraction && pro->pos.y > pro->drawRadius) continue; if (pro->s3domodel) { if (pro->s3domodel->type == MODELTYPE_S3O) { unitDrawer->QueS3ODraw(pro, pro->s3domodel->textureType); } else { pro->DrawUnitPart(); } } pro->tempdist = pro->pos.dot(camera->forward); distset.insert(pro); } } }
void CLaser::Fire() { //Get matrix for current player location and forward vector tlx::CMatrix4x4 matrix; GetParent()->GetMatrix(matrix.m); //Create forward vector (z axis) CVector3 direction(matrix.m[8], matrix.m[9], matrix.m[10]); //Get position from matrix //Since we've already got the matrix it's slightly more efficient than calling GetParent()->GetCenterPoint() CVector3 pos(matrix.m[12], OFF_SCREEN_Y, matrix.m[14]); //Calculate the rotation of the parent entity, just so it only needs to be calculated once float rotation = GetParent()->GetRotation(); //Makes the space between invisible bullets 2.0f instead of 1.0f direction *= 2.0f; for (int i = 0; i < 70; i++) { CProjectile* bullet = new CProjectile(); bullet->SetPosition(pos); bullet->SetRotation(rotation); bullet->SetDamage(GetDamage()); bullet->SetSpeed(GetProjSpeed()); bullet->SetParent(GetParent()); bullet->SetExplodeable(false); GetBulletList()->push_back(unique_ptr<CProjectile>(bullet)); //Increment position of next bullet pos += direction; } }
//bool IGameController::OnEntity(int Index, vec2 Pos) bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Number) { if (Index < 0) return false; int Type = -1; int SubType = 0; int x,y; x=(Pos.x-16.0f)/32.0f; y=(Pos.y-16.0f)/32.0f; int sides[8]; sides[0]=GameServer()->Collision()->Entity(x,y+1, Layer); sides[1]=GameServer()->Collision()->Entity(x+1,y+1, Layer); sides[2]=GameServer()->Collision()->Entity(x+1,y, Layer); sides[3]=GameServer()->Collision()->Entity(x+1,y-1, Layer); sides[4]=GameServer()->Collision()->Entity(x,y-1, Layer); sides[5]=GameServer()->Collision()->Entity(x-1,y-1, Layer); sides[6]=GameServer()->Collision()->Entity(x-1,y, Layer); sides[7]=GameServer()->Collision()->Entity(x-1,y+1, Layer); if(Index == ENTITY_SPAWN) m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos; else if(Index == ENTITY_SPAWN_RED) m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos; else if(Index == ENTITY_SPAWN_BLUE) m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = Pos; else if(Index == ENTITY_DOOR) { for(int i = 0; i < 8;i++) { if (sides[i] >= ENTITY_LASER_SHORT && sides[i] <= ENTITY_LASER_LONG) { new CDoor ( &GameServer()->m_World, //GameWorld Pos, //Pos pi / 4 * i, //Rotation 32 * 3 + 32 *(sides[i] - ENTITY_LASER_SHORT) * 3, //Length Number //Number ); } } } else if(Index == ENTITY_CRAZY_SHOTGUN_EX) { int Dir; if(!Flags) Dir = 0; else if(Flags == ROTATION_90) Dir = 1; else if(Flags == ROTATION_180) Dir = 2; else Dir = 3; float Deg = Dir * (pi / 2); CProjectile *bullet = new CProjectile ( &GameServer()->m_World, WEAPON_SHOTGUN, //Type -1, //Owner Pos, //Pos vec2(sin(Deg), cos(Deg)), //Dir -2, //Span true, //Freeze true, //Explosive 0, //Force (g_Config.m_SvShotgunBulletSound)?SOUND_GRENADE_EXPLODE:-1,//SoundImpact WEAPON_SHOTGUN,//Weapon Layer, Number ); bullet->SetBouncing(2 - (Dir % 2)); } else if(Index == ENTITY_CRAZY_SHOTGUN) { int Dir; if(!Flags) Dir=0; else if(Flags == (TILEFLAG_ROTATE)) Dir = 1; else if(Flags == (TILEFLAG_VFLIP|TILEFLAG_HFLIP)) Dir = 2; else Dir = 3; float Deg = Dir * ( pi / 2); CProjectile *bullet = new CProjectile ( &GameServer()->m_World, WEAPON_SHOTGUN, //Type -1, //Owner Pos, //Pos vec2(sin(Deg), cos(Deg)), //Dir -2, //Span true, //Freeze false, //Explosive 0, SOUND_GRENADE_EXPLODE, WEAPON_SHOTGUN, //Weapon Layer, Number ); bullet->SetBouncing(2 - (Dir % 2)); } if(Index == ENTITY_ARMOR_1) Type = POWERUP_ARMOR; else if(Index == ENTITY_HEALTH_1) Type = POWERUP_HEALTH; else if(Index == ENTITY_WEAPON_SHOTGUN) { Type = POWERUP_WEAPON; SubType = WEAPON_SHOTGUN; } else if(Index == ENTITY_WEAPON_GRENADE) { Type = POWERUP_WEAPON; SubType = WEAPON_GRENADE; } else if(Index == ENTITY_WEAPON_RIFLE) { Type = POWERUP_WEAPON; SubType = WEAPON_RIFLE; } //else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups) else if(Index == ENTITY_POWERUP_NINJA) { Type = POWERUP_NINJA; SubType = WEAPON_NINJA; } else if(Index >= ENTITY_LASER_FAST_CW && Index <= ENTITY_LASER_FAST_CCW) { int sides2[8]; sides2[0]=GameServer()->Collision()->Entity(x, y + 2, Layer); sides2[1]=GameServer()->Collision()->Entity(x + 2, y + 2, Layer); sides2[2]=GameServer()->Collision()->Entity(x + 2, y, Layer); sides2[3]=GameServer()->Collision()->Entity(x + 2, y - 2, Layer); sides2[4]=GameServer()->Collision()->Entity(x,y - 2, Layer); sides2[5]=GameServer()->Collision()->Entity(x - 2, y - 2, Layer); sides2[6]=GameServer()->Collision()->Entity(x - 2, y, Layer); sides2[7]=GameServer()->Collision()->Entity(x - 2, y + 2, Layer); float AngularSpeed = 0.0; int Ind=Index-ENTITY_LASER_STOP; int M; if( Ind < 0) { Ind = -Ind; M = 1; } else if(Ind == 0) M = 0; else M = -1; if(Ind == 0) AngularSpeed = 0.0f; else if(Ind == 1) AngularSpeed = pi / 360; else if(Ind == 2) AngularSpeed = pi / 180; else if(Ind == 3) AngularSpeed = pi / 90; AngularSpeed *= M; for(int i=0; i<8;i++) { if(sides[i] >= ENTITY_LASER_SHORT && sides[i] <= ENTITY_LASER_LONG) { CLight *Lgt = new CLight(&GameServer()->m_World, Pos, pi / 4 * i, 32 * 3 + 32 * (sides[i] - ENTITY_LASER_SHORT) * 3, Layer, Number); Lgt->m_AngularSpeed = AngularSpeed; if(sides2[i] >= ENTITY_LASER_C_SLOW && sides2[i] <= ENTITY_LASER_C_FAST) { Lgt->m_Speed = 1 + (sides2[i] - ENTITY_LASER_C_SLOW) * 2; Lgt->m_CurveLength = Lgt->m_Length; } else if(sides2[i] >= ENTITY_LASER_O_SLOW && sides2[i] <= ENTITY_LASER_O_FAST) { Lgt->m_Speed = 1 + (sides2[i] - ENTITY_LASER_O_SLOW) * 2; Lgt->m_CurveLength = 0; } else Lgt->m_CurveLength = Lgt->m_Length; } } } else if(Index >= ENTITY_DRAGGER_WEAK && Index <= ENTITY_DRAGGER_STRONG) { new CDraggerTeam(&GameServer()->m_World, Pos, Index - ENTITY_DRAGGER_WEAK + 1, false, Layer, Number); } else if(Index >= ENTITY_DRAGGER_WEAK_NW && Index <= ENTITY_DRAGGER_STRONG_NW) { new CDraggerTeam(&GameServer()->m_World, Pos, Index - ENTITY_DRAGGER_WEAK_NW + 1, true, Layer, Number); } else if(Index == ENTITY_PLASMAE) { new CGun(&GameServer()->m_World, Pos, false, true, Layer, Number); } else if(Index == ENTITY_PLASMAF) { new CGun(&GameServer()->m_World, Pos, true, false, Layer, Number); } else if(Index == ENTITY_PLASMA) { new CGun(&GameServer()->m_World, Pos, true, true, Layer, Number); } else if(Index == ENTITY_PLASMAU) { new CGun(&GameServer()->m_World, Pos, false, false, Layer, Number); } if(Type != -1) { //CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType); CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType, Layer, Number); pPickup->m_Pos = Pos; return true; } return false; }
void CCharacter::FireWeapon() { if(m_ReloadTimer != 0) return; DoWeaponSwitch(); vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); bool FullAuto = false; if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_LASER) FullAuto = true; // check if we gonna fire bool WillFire = false; if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses) WillFire = true; if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo) WillFire = true; if(!WillFire) return; // check for ammo if(!m_aWeapons[m_ActiveWeapon].m_Ammo) { // 125ms is a magical limit of how fast a human can click m_ReloadTimer = 125 * Server()->TickSpeed() / 1000; GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO); return; } vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f; switch(m_ActiveWeapon) { case WEAPON_HAMMER: { // reset objects Hit m_NumObjectsHit = 0; GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE); CCharacter *apEnts[MAX_CLIENTS]; int Hits = 0; int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { CCharacter *pTarget = apEnts[i]; if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)) continue; // set his velocity to fast upward (for now) if(length(pTarget->m_Pos-ProjStartPos) > 0.0f) GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f); else GameServer()->CreateHammerHit(ProjStartPos); vec2 Dir; if (length(pTarget->m_Pos - m_Pos) > 0.0f) Dir = normalize(pTarget->m_Pos - m_Pos); else Dir = vec2(0.f, -1.f); pTarget->TakeDamage(vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); Hits++; } // if we Hit anything, we have to wait for the reload if(Hits) m_ReloadTimer = Server()->TickSpeed()/3; } break; case WEAPON_GUN: { CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GUN, m_pPlayer->GetCID(), ProjStartPos, Direction, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime), 1, 0, 0, -1, WEAPON_GUN); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE); } break; case WEAPON_SHOTGUN: { int ShotSpread = 2; CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(ShotSpread*2+1); for(int i = -ShotSpread; i <= ShotSpread; ++i) { float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; float a = GetAngle(Direction); a += Spreading[i+2]; float v = 1-(absolute(i)/(float)ShotSpread); float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v); CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, m_pPlayer->GetCID(), ProjStartPos, vec2(cosf(a), sinf(a))*Speed, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime), 1, 0, 0, -1, WEAPON_SHOTGUN); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); } Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE); } break; case WEAPON_GRENADE: { CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE, m_pPlayer->GetCID(), ProjStartPos, Direction, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime), 1, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE); } break; case WEAPON_LASER: { new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_LASER_FIRE); } break; case WEAPON_NINJA: { // reset Hit objects m_NumObjectsHit = 0; m_Ninja.m_ActivationDir = Direction; m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000; m_Ninja.m_OldVelAmount = length(m_Core.m_Vel); GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE); } break; } m_AttackTick = Server()->Tick(); if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited m_aWeapons[m_ActiveWeapon].m_Ammo--; if(!m_ReloadTimer) m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000; }
bool CSpammer::ShootRocket(EntityId target) { IEntityClass* pAmmoClass = m_fireParams->fireparams.ammo_type_class; int ammoCount = m_pWeapon->GetAmmoCount(pAmmoClass); CActor *pOwnerActor = m_pWeapon->GetOwnerActor(); const bool playerIsShooter = pOwnerActor ? pOwnerActor->IsPlayer() : false; const bool clientIsShooter = pOwnerActor ? pOwnerActor->IsClient() : false; bool bHit = false; ray_hit rayhit; rayhit.pCollider = 0; Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE, &bHit, &rayhit); Vec3 pos = GetFiringPos(hit); Vec3 dir = GetFiringDir(hit, pos); Vec3 vel = GetFiringVelocity(dir); int flags = CItem::eIPAF_Default; if (IsProceduralRecoilEnabled() && pOwnerActor) { pOwnerActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn, m_fireParams->proceduralRecoilParams.arms); } float speedOverride = -1.f; GetWeapon()->PlayAction(GetFragmentIds().fire, 0, false, flags, speedOverride); CheckNearMisses(hit, pos, dir, (hit-pos).len(), 1.0f); CProjectile* pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, false); const EntityId weaponOwnerId = m_pWeapon->GetOwnerId(); EntityId ammoId = 0; if (pAmmo) { ammoId = pAmmo->GetEntityId(); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); pAmmo->SetParams(CProjectile::SProjectileDesc( weaponOwnerId, m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_fireParams->fireparams.damage, m_fireParams->fireparams.damage_drop_min_distance, m_fireParams->fireparams.damage_drop_per_meter, m_fireParams->fireparams.damage_drop_min_damage, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed())); // this must be done after owner is set pAmmo->InitWithAI(); pAmmo->SetDestination(target); pAmmo->Launch(pos, dir, vel, m_speed_scale); m_projectileId = ammoId; if (clientIsShooter && pAmmo->IsPredicted() && gEnv->IsClient() && gEnv->bServer) { pAmmo->GetGameObject()->BindToNetwork(); } } if (m_pWeapon->IsServer()) { const char *ammoName = pAmmoClass != NULL ? pAmmoClass->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, 1, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); } OnShoot(weaponOwnerId, ammoId, pAmmoClass, pos, dir, vel); if(playerIsShooter) { const SThermalVisionParams& thermalParams = m_fireParams->thermalVisionParams; m_pWeapon->AddShootHeatPulse(pOwnerActor, thermalParams.weapon_shootHeatPulse, thermalParams.weapon_shootHeatPulseTime, thermalParams.owner_shootHeatPulse, thermalParams.owner_shootHeatPulseTime); } m_muzzleEffect.Shoot(this, hit, m_barrelId); RecoilImpulse(pos, dir); m_fired = true; m_next_shot += m_next_shot_dt; if (++m_barrelId == m_fireParams->fireparams.barrel_count) m_barrelId = 0; ammoCount--; int clipSize = GetClipSize(); if (clipSize != -1) { if (clipSize!=0) m_pWeapon->SetAmmoCount(pAmmoClass, ammoCount); else m_pWeapon->SetInventoryAmmoCount(pAmmoClass, ammoCount); } m_pWeapon->RequestShoot(pAmmoClass, pos, dir, vel, hit, m_speed_scale, pAmmo? pAmmo->GetGameObject()->GetPredictionHandle() : 0, false); return true; }
void CProjectileDrawer::DrawProjectilesMiniMap() { GML_RECMUTEX_LOCK(proj); // DrawProjectilesMiniMap typedef std::set<CProjectile*> ProjectileSet; typedef std::set<CProjectile*>::const_iterator ProjectileSetIt; typedef std::map<int, ProjectileSet> ProjectileBin; typedef std::map<int, ProjectileSet>::const_iterator ProjectileBinIt; for (int modelType = MODELTYPE_3DO; modelType < MODELTYPE_OTHER; modelType++) { const ProjectileBin& projectileBin = modelRenderers[modelType]->GetProjectileBin(); if (!projectileBin.empty()) { for (ProjectileBinIt binIt = projectileBin.begin(); binIt != projectileBin.end(); ++binIt) { CVertexArray* lines = GetVertexArray(); CVertexArray* points = GetVertexArray(); lines->Initialize(); lines->EnlargeArrays((binIt->second).size() * 2, 0, VA_SIZE_C); points->Initialize(); points->EnlargeArrays((binIt->second).size(), 0, VA_SIZE_C); for (ProjectileSetIt setIt = (binIt->second).begin(); setIt != (binIt->second).end(); ++setIt) { CProjectile* p = *setIt; CUnit *owner = p->owner(); if ((owner && (owner->allyteam == gu->myAllyTeam)) || gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam)) { p->DrawOnMinimap(*lines, *points); } } lines->DrawArrayC(GL_LINES); points->DrawArrayC(GL_POINTS); } } } if (!renderProjectiles.empty()) { CVertexArray* lines = GetVertexArray(); CVertexArray* points = GetVertexArray(); lines->Initialize(); lines->EnlargeArrays(renderProjectiles.size() * 2, 0, VA_SIZE_C); points->Initialize(); points->EnlargeArrays(renderProjectiles.size(), 0, VA_SIZE_C); for (std::set<CProjectile*>::iterator it = renderProjectiles.begin(); it != renderProjectiles.end(); ++it) { CProjectile* p = *it; const CUnit* owner = p->owner(); if ((owner && (owner->allyteam == gu->myAllyTeam)) || gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam)) { p->DrawOnMinimap(*lines, *points); } } lines->DrawArrayC(GL_LINES); points->DrawArrayC(GL_POINTS); } }
void CLTagSingle::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int predictionHandle) { IEntityClass* ammo = m_fireParams->fireparams.ammo_type_class; int weaponAmmoCount = m_pWeapon->GetAmmoCount(ammo); int ammoCount = weaponAmmoCount; CActor* pOwnerActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pOwnerActor ? pOwnerActor->IsPlayer() : false; if (IsProceduralRecoilEnabled() && pOwnerActor) { pOwnerActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn, m_fireParams->proceduralRecoilParams.arms); } m_pWeapon->PlayAction(GetFragmentIds().fire, 0, false, CItem::eIPAF_Default); CProjectile *pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, true); CLTAGGrenade* pGrenade = static_cast<CLTAGGrenade*>(pAmmo); if (pGrenade) { CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); pGrenade->SetParams(CProjectile::SProjectileDesc( m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_fireParams->fireparams.damage, 0.f, 0.f, 0.f, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed())); // this must be done after owner is set pGrenade->InitWithAI(); pGrenade->SetDestination(m_pWeapon->GetDestination()); pGrenade->SetGrenadeType(m_grenadeType); pGrenade->Launch(pos, dir, vel, m_speed_scale); m_projectileId = pGrenade->GetEntity()->GetId(); } if (m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, 1, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); #ifdef SERVER_CHECKS if (pOwnerActor && m_pWeapon->IsServerSpawn(ammo)) { int inventoryAmmoCount = m_pWeapon->GetInventoryAmmoCount(ammo); int totalAmmoCount=weaponAmmoCount+inventoryAmmoCount; // this needed seeing as how this seems to use weaponAmmo or inventoryAmmo but NOT both? if (totalAmmoCount <= 0) { g_pGame->GetAntiCheatManager()->FlagActivity(eCT_ServerSpawnedAmmoUsed, pOwnerActor->GetChannelId()); } } #endif } m_muzzleEffect.Shoot(this, hit, m_barrelId); RecoilImpulse(pos, dir); m_fired = true; m_next_shot = 0.0f; ammoCount--; if(ammoCount<0) ammoCount = 0; if (m_pWeapon->IsServer()) { int clipSize = GetClipSize(); if (clipSize != -1) { if (clipSize != 0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } } OnShoot(m_pWeapon->GetOwnerId(), pAmmo?pAmmo->GetEntity()->GetId():0, ammo, pos, dir, vel); if(playerIsShooter) { const SThermalVisionParams& thermalParams = m_fireParams->thermalVisionParams; m_pWeapon->AddShootHeatPulse(pOwnerActor, thermalParams.weapon_shootHeatPulse, thermalParams.weapon_shootHeatPulseTime, thermalParams.owner_shootHeatPulse, thermalParams.owner_shootHeatPulseTime); } if (OutOfAmmo()) m_pWeapon->OnOutOfAmmo(ammo); if (pAmmo && predictionHandle && pOwnerActor) { pAmmo->GetGameObject()->RegisterAsValidated(pOwnerActor->GetGameObject(), predictionHandle); pAmmo->GetGameObject()->BindToNetwork(); } else if (pAmmo && pAmmo->IsPredicted() && gEnv->IsClient() && gEnv->bServer && pOwnerActor && pOwnerActor->IsClient()) { pAmmo->GetGameObject()->BindToNetwork(); } m_pWeapon->RequireUpdate(eIUS_FireMode); }
void CProjectile::HandleTouch(HOBJECT hObj) { if (m_bObjectRemoved) return; // Don't process any touches until this has been cleared... if (m_bProcessInvImpact) return; // Let it get out of our bounding box... if (hObj == m_hFiredFrom) return; CCharacterHitBox* pHitBox = LTNULL; // If we've hit a character (or body), let its hit box take control... if (IsCharacter(hObj)) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj); if (pChar) { hObj = pChar->GetHitBox(); } } else if (IsBody(hObj)) { Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); if (pBody) { hObj = pBody->GetHitBox(); } } if (IsCharacterHitBox(hObj)) { pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj); if (!pHitBox) return; if (pHitBox->GetModelObject() == m_hFiredFrom) return; } // Don't hit our own type of projectiles (for multi-projectile weapons // and projectiles that stick to objects)... if (IsKindOf(hObj, m_hObject)) { CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj); if (pObj) { if (pObj->GetFiredFrom() == m_hFiredFrom) { return; } } } // See if we want to impact on this object... uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj); if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return; LTBOOL bIsWorld = IsMainWorld(hObj); // Don't impact on non-solid objects...unless it is a CharacterHitBox // object... uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj); if (!bIsWorld && !(dwFlags & FLAG_SOLID)) { if (pHitBox) { // See if we really impacted on the box... if (pHitBox->DidProjectileImpact(this)) { // This is the object that we really hit... hObj = pHitBox->GetModelObject(); } else { return; } } else if (!(dwFlags & FLAG_RAYHIT)) { // If we have ray hit set to true, projectiles should // impact on us too... return; } } // See if we hit the sky... if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj))) { CollisionInfo info; g_pLTServer->GetLastCollision(&info); SurfaceType eType = GetSurfaceType(info); if (eType == ST_SKY) { RemoveObject(); return; } else if (eType == ST_INVISIBLE) { // Update 1.002 [KLS] - If multiplayer and we hit an invisible // surface, just treat it like a normal surface... if (!IsMultiplayerGame()) { m_bProcessInvImpact = LTTRUE; g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos); g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel); m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime()); // Make sure this new position is inside the world...else // just blow up... if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos)) { return; } } } } HandleImpact(hObj); }
//------------------------------------------------------------------------ void CShotgun::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int ph) { assert(0 == ph); IEntityClass *ammo = m_pShared->fireparams.ammo_type_class; const char *action = m_pShared->actions.fire_cock.c_str(); CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor?pActor->IsPlayer():false; int ammoCount = m_pWeapon->GetAmmoCount(ammo); if(m_pShared->fireparams.clip_size==0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); if(ammoCount == 1) action = m_pShared->actions.fire.c_str(); m_pWeapon->ResetAnimation(); m_pWeapon->PlayAction(action, 0, false, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); Vec3 pdir; // SHOT HERE for(int i = 0; i < m_pShared->shotgunparams.pellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(ammo, true); if(pAmmo) { pdir = ApplySpread(dir, m_pShared->shotgunparams.spread); int hitTypeId = g_pGame->GetGameRules()->GetHitTypeId(m_pShared->fireparams.hit_type.c_str()); pAmmo->SetParams(m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_pShared->shotgunparams.pelletdamage, hitTypeId, playerIsShooter?m_pShared->fireparams.damage_drop_per_meter:0.0f, m_pShared->fireparams.damage_drop_min_distance); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->SetRemote(true); pAmmo->Launch(pos, pdir, vel); bool emit = false; if(m_pWeapon->GetStats().fp) emit = (!m_pShared->tracerparams.geometryFP.empty() || !m_pShared->tracerparams.effectFP.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0)); else emit = (!m_pShared->tracerparams.geometry.empty() || !m_pShared->tracerparams.effect.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0)); if(emit) EmitTracer(pos,hit,false); m_projectileId = pAmmo->GetEntity()->GetId(); } } m_pWeapon->OnShoot(m_pWeapon->GetOwnerId(), 0, ammo, pos, dir, vel); if(m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_pShared->shotgunparams.pellets, (void *)m_pWeapon->GetEntityId())); } MuzzleFlashEffect(true); RejectEffect(); m_fired = true; m_next_shot = 0.0f; ammoCount--; if(m_pWeapon->IsServer()) { if(m_pShared->fireparams.clip_size != -1) { if(m_pShared->fireparams.clip_size!=0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } } if((ammoCount<1) && !m_pShared->fireparams.slider_layer.empty()) { const char *slider_back_layer = m_pShared->fireparams.slider_layer.c_str(); m_pWeapon->PlayLayer(slider_back_layer, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); } m_pWeapon->RequireUpdate(eIUS_FireMode); }