Skip to content

Commit

Permalink
New Weapon: Puppetee Hammer
Browse files Browse the repository at this point in the history
  • Loading branch information
Hu1night committed Mar 9, 2024
1 parent 796a3c4 commit 309cedb
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,8 @@ set_src(GAME_SERVER GLOB_RECURSE src/game/server
weapons/ninja.h
weapons/pistol.cpp
weapons/pistol.h
weapons/puppeteehammer.cpp
weapons/puppeteehammer.h
weapons/shotgun.cpp
weapons/shotgun.h
)
Expand Down
5 changes: 5 additions & 0 deletions src/game/server/entities/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class CCharacter : public CEntity
void ForceSetWeapon(int Slot, int Type, int Ammo = -1);
void SetOverrideWeapon(int Slot, int Type, int Ammo = -1);
void SetPowerUpWeapon(int Type, int Ammo = -1);
void SetPowerUpWeaponPointer(CWeapon *Weapon) { m_pPowerupWeapon = Weapon; }

void SetEndlessHook(bool Enable);

Expand Down Expand Up @@ -291,6 +292,10 @@ class CCharacter : public CEntity
int m_MaxArmor; // Hunter

vec2 GetDirection() { return normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); } // Hunter
vec2 GetAimPos() { return vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY); } // Hunter
CNetObj_PlayerInput GetLatestInput() { return m_LatestInput; } // Hunter
CNetObj_PlayerInput GetLatestPrevPrevInput() { return m_LatestPrevPrevInput; } // Hunter
void SetQueuedWeaponSlot(int WeaponSlot) { m_QueuedWeaponSlot = WeaponSlot; }
};

enum
Expand Down
2 changes: 2 additions & 0 deletions src/game/server/weapons.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ REGISTER_WEAPON(WEAPON_ID_EXPLODINGLASER, CExplodingLaser)

REGISTER_WEAPON(WEAPON_ID_HUNTHAMMER, CHuntHammer) // Hunter
//REGISTER_WEAPON(WEAPON_ID_JUGNINJA, CJugNinja) // Hunter
REGISTER_WEAPON(WEAPON_ID_PUPPETEEHAMMER, CPuppeteeHammer) // Hunter

#else

Expand All @@ -28,6 +29,7 @@ REGISTER_WEAPON(WEAPON_ID_HUNTHAMMER, CHuntHammer) // Hunter

#include "weapons/hunthammer.h" // Hunter
//#include "weapons/jugninja.h" // Hunter
#include "weapons/puppeteehammer.h"

enum
{
Expand Down
2 changes: 1 addition & 1 deletion src/game/server/weapons/hunthammer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void CHuntHammer::Snap(int SnappingClient, int OtherMode)
if(Character()->GetPlayer()->GetCID() != SnappingClient)
return;

if(!Character()->m_IsFiring || m_ReloadTimer > 1)
if(!(Character()->GetLatestInput().m_Fire & 1) || m_ReloadTimer > 1)
return;

CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, IndicatorSnapID, sizeof(CNetObj_Laser)));
Expand Down
159 changes: 159 additions & 0 deletions src/game/server/weapons/puppeteehammer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include "puppeteehammer.h"
#include <game/generated/server_data.h>
#include <game/server/entities/projectile.h>

CPuppeteeHammer::CPuppeteeHammer(CCharacter *pOwnerChar) :
CWeapon(pOwnerChar)
{
m_MaxAmmo = 10;
m_AmmoRegenTime = 1;
m_FireDelay = 500;
m_IsKeepFiring = false;
m_PrevTickPuppets = 0;
mem_zero(m_aPuppetCID, sizeof(m_aPuppetCID));
mem_zero(m_aPuppetsDirPos, sizeof(m_aPuppetsDirPos));
}

void CPuppeteeHammer::Tick()
{
CWeapon::Tick();

int CharCount = 0;
CCharacter *apChar[MAX_PUPPETS] = {0};

for(int i = 0; i < MAX_PUPPETS; i++)
{
if(!m_aPuppetCID[i])
continue;

apChar[i] = GameServer()->GetPlayerChar(m_aPuppetCID[i] - 1);
if(apChar[i])
CharCount++;
else
m_aPuppetCID[i] = 0;
}

if(!CharCount) // Just do nothing
{}
else if((Character()->GetLatestPrevPrevInput().m_Fire & 1) && !(Character()->GetLatestInput().m_Fire & 1) && IsReloading()) // 松发让傀儡开火
{
vec2 AimPos = Pos() + Character()->GetAimPos();

for(int i = 0; i < MAX_PUPPETS; i++)
{
CCharacter *pChr = apChar[i];
if(!pChr)
continue;

CWeapon *pChrWeapon = pChr->CurrentWeapon();
if(!pChrWeapon)
continue;

vec2 AimDir = normalize(AimPos - pChr->m_Pos);

pChrWeapon->HandleFire(AimDir);
}
}
else if((m_IsKeepFiring && !IsReloading()) // Pressing
|| (m_PrevTickPuppets != CharCount)) // Update
{
vec2 OwnerDir = Character()->GetDirection();
vec2 PuppetsDir = OwnerDir * clamp(length(Character()->GetAimPos()), 48.f, 128.f);
int a = 0;

for(int i = 0; i < MAX_PUPPETS; i++)
{
if(!m_aPuppetCID[i])
continue;

a++;
m_aPuppetsDirPos[i] = PuppetsDir + (vec2(-OwnerDir.y, OwnerDir.x) * ((a / 2) * 32.f * (a % 2 ? 1 : -1) + ((CharCount % 2) * 16.f)));
}
}

if(CharCount)
{
//SetPowerUpWeaponPointer(this);

int OwnerQueuedWeaponSlot = Character()->GetLatestInput().m_WantedWeapon - 1;

for(int i = 0; i < MAX_PUPPETS; i++)
{
CCharacter *pChr = apChar[i];
if(!pChr)
continue;

//pChr->Freeze(5, true);

pChr->SetQueuedWeaponSlot(OwnerQueuedWeaponSlot);

// TODO: replace MoveBox
pChr->Core()->m_Vel = Pos() + m_aPuppetsDirPos[i] - pChr->Core()->m_Pos;
GameServer()->Collision()->MoveBox(&pChr->Core()->m_Pos, &pChr->Core()->m_Vel, vec2(GetProximityRadius(), GetProximityRadius()), 0.f);
pChr->Core()->m_Vel = vec2(0.f, 0.f);
}
}

m_IsKeepFiring = m_IsKeepFiring ? (Character()->GetLatestInput().m_Fire & 1) : false;
m_PrevTickPuppets = CharCount;
}

void CPuppeteeHammer::Fire(vec2 Direction)
{
int ClientID = Character()->GetPlayer()->GetCID();
GameWorld()->CreateSound(Pos(), SOUND_HAMMER_FIRE);

GameServer()->Antibot()->OnHammerFire(ClientID);

m_IsKeepFiring = true;

if(Character()->IsSolo() || Character()->m_Hit & CCharacter::DISABLE_HIT_HAMMER)
return;

vec2 HammerHitPos = Pos() + Direction * GetProximityRadius() * 0.75f;

CCharacter *apEnts[MAX_CLIENTS];
int Num = GameWorld()->FindEntities(HammerHitPos, GetProximityRadius() * 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))
if((pTarget == Character() || (pTarget->IsAlive() && pTarget->IsSolo())))
continue;

bool IsPuppet = false;
int TargetCID = pTarget->GetPlayer()->GetCID();
for(int i = 0; i < MAX_PUPPETS; i++) // Check Puppet
{
if(TargetCID != m_aPuppetCID[i] - 1)
continue;

IsPuppet = true;
break;
}
if(IsPuppet)
continue;

for(int i = 0; i < MAX_PUPPETS; i++) // Set Puppet
{
if(m_aPuppetCID[i])
continue;

m_aPuppetCID[i] = TargetCID + 1;
break;
}

// set his velocity to fast upward (for now)
if(length(pTarget->m_Pos - HammerHitPos) > 0.0f)
GameWorld()->CreateHammerHit(pTarget->m_Pos - normalize(pTarget->m_Pos - HammerHitPos) * GetProximityRadius() * 0.5f);
else
GameWorld()->CreateHammerHit(HammerHitPos);

pTarget->TakeDamage(vec2(0.f, -0.5f), 0, ClientID, WEAPON_HAMMER, GetWeaponID(), false); // 法师近战

GameServer()->Antibot()->OnHammerHit(ClientID);
}
}
23 changes: 23 additions & 0 deletions src/game/server/weapons/puppeteehammer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef GAME_SERVER_WEAPONS_PUPPETEEHAMMER_H
#define GAME_SERVER_WEAPONS_PUPPETEEHAMMER_H

#include <game/server/weapon.h>

class CPuppeteeHammer : public CWeapon
{
public:
CPuppeteeHammer(CCharacter *pOwnerChar);

void Tick() override;
void Fire(vec2 Direction) override;
int GetType() override { return WEAPON_HAMMER; }
bool IsPowerupOver() { return false; }
private:
enum { MAX_PUPPETS = 4, };
int m_aPuppetCID[MAX_PUPPETS];
vec2 m_aPuppetsDirPos[MAX_PUPPETS];
bool m_IsKeepFiring;
int m_PrevTickPuppets;
};

#endif // GAME_SERVER_WEAPONS_PUPPETEEHAMMER_H

0 comments on commit 309cedb

Please sign in to comment.