📄 playerobj.cpp
字号:
pServerDE->GetObjectPos(m_hObject, &pos);
pos.y += 50.0;
pServerDE->MoveObject(m_hObject, &pos);
}
// This is a KLUDGE to fix problem with sinking through
// the ground when switching to spectator mode. We'll
// process a frame before we actually switch...
if (m_bSpectatorMode)
{
DDWORD dwFlags = pServerDE->GetObjectFlags(m_hObject);
DVector dims;
VEC_INIT(dims)
HSTRING hstr = pServerDE->FormatString(IDS_GENERAL_SPECTATORON);
SendConsoleMessage(pServerDE->GetStringData(hstr));
pServerDE->FreeString(hstr);
// dwFlags &= ~(FLAG_SHADOW | FLAG_TOUCH_NOTIFY | FLAG_SOLID);
dwFlags &= ~(FLAG_TOUCH_NOTIFY | FLAG_SOLID);
dwFlags |= FLAG_GOTHRUWORLD;
pServerDE->SetObjectFlags(m_hObject, dwFlags);
// pServerDE->SetObjectDims(m_hObject, &dims);
// pServerDE->SetVelocity(m_hObject, &dims);
// pServerDE->SetAcceleration(m_hObject, &dims);
}
else
{
DDWORD dwFlags = pServerDE->GetObjectFlags(m_hObject);
dwFlags &= ~FLAG_GOTHRUWORLD;
dwFlags |= FLAG_TOUCH_NOTIFY | FLAG_SOLID;
// dwFlags |= FLAG_SHADOW | FLAG_TOUCH_NOTIFY | FLAG_SOLID;
// DVector dims = {12.0, gCharacterValues[m_nCharacter].fHeightStanding/2, 12.0};
HSTRING hstr = pServerDE->FormatString(IDS_GENERAL_SPECTATOROFF);
SendConsoleMessage(pServerDE->GetStringData(hstr));
pServerDE->FreeString(hstr);
pServerDE->SetObjectFlags(m_hObject, dwFlags);
}
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::Respawn()
//
// PURPOSE: Resets player attributes
//
// --------------------------------------------------------------------------- //
void CPlayerObj::Respawn()
{
// Get our server pointer...
CServerDE* pServerDE = GetServerDE();
// If we're currently dead in our humiliation any, gib...
if (pServerDE->GetModelAnimation(m_hObject) == m_Anim_Sound.m_nAnim_HUMILIATION[3])
{
if (m_bDead)
{
int nType = m_damage.GetLastDamageType();
DFLOAT fDamage = m_damage.GetLastDamageAmount();
DVector vDir;
m_damage.GetLastDamageDirection(&vDir);
CreateGibs(vDir, ((int)m_damage.GetMass())>>5, nType, fDamage);
}
}
// Check for spectator mode...
if (m_bSpectatorMode)
ToggleSpectatorMode();
// Respawn as necessary...
if (!m_damage.IsDead() || g_pBloodServerShell->GetGameType() != GAMETYPE_SINGLE)
{
// Set up the filenames
SetCharacter(m_nCharacter);
// Reset any hidden nodes
AIShared.ResetNodes(m_hObject);
// Set flags
DDWORD dwFlags = FLAG_VISIBLE | FLAG_MODELKEYS | FLAG_YROTATION | FLAG_ANIMTRANSITION | FLAG_TOUCH_NOTIFY | FLAG_SOLID | FLAG_STAIRSTEP | FLAG_SHADOW;
// DDWORD dwFlags = FLAG_SOLID | FLAG_VISIBLE | FLAG_TOUCH_NOTIFY | FLAG_STAIRSTEP | FLAG_SHADOW | FLAG_KEEPALIVE | FLAG_FULLPOSITIONRES | FLAG_FORCECLIENTUPDATE | FLAG_MODELKEYS | FLAG_YROTATION | FLAG_ANIMTRANSITION | FLAG_GRAVITY;
pServerDE->SetObjectFlags(m_hObject, dwFlags);
DVector dims;
VEC_INIT(dims)
pServerDE->SetVelocity(m_hObject, &dims);
// m_fEyeLevel = gCharacterValues[m_nCharacter].fEyeLevelStanding;
// SendMessageToClient(SMSG_EYELEVEL);
// m_damage.Reset();
m_damage.SetHitPoints(100);
m_damage.SetArmorPoints(0);
m_bDead = DFALSE;
m_fAirLevel = MAX_AIR_LEVEL;
m_fDeathTimer = 0;
m_fSlowDeathSafeTimer = 0;
m_fSlowDeathStayTimer = 0;
m_bInSlowDeath = DFALSE;
m_bBurning = DFALSE;
if (g_pBloodServerShell->IsMultiplayerGame())
{
DFLOAT fDeltaTime = g_pServerDE->GetTime() - s_fCreatedTime;
if (fDeltaTime > 5.0f && IsRandomChance(65))
{
PlayVoiceGroupEventOnClient(VME_SPAWN);
}
SetMultiplayerAmmo();
}
else
{
for (int i = AMMO_BULLET; i <= AMMO_MAXAMMOTYPES; i++)
m_InventoryMgr.SetAmmoCount(i, 0.0f);
m_InventoryMgr.SetAmmoCount(AMMO_BULLET, DEFAULT_BULLETS);
}
}
// Dump the bomb list.
if( m_pBombList )
{
ObjectLink* pLink = m_pBombList->m_pFirstLink;
while( pLink )
{
g_pServerDE->RemoveObject( pLink->m_hObject );
pLink = pLink->m_pNext;
}
pServerDE->RelinquishList( m_pBombList );
m_pBombList = DNULL;
}
UpdateClientPhysics(); // (to make sure they have their model around)
TeleportClientToServerPos();
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::GoToStartPoint()
//
// PURPOSE: Teleports the player to a startpoint.
//
// --------------------------------------------------------------------------- //
void CPlayerObj::GoToStartPoint()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !g_pBloodServerShell)
return;
DVector pos;
VEC_INIT(pos)
// Get all the Blood 2 start points...
ObjectList* pList = pServerDE->FindNamedObjects("Blood2StartPoint");
if (!pList || !pList->m_pFirstLink || pList->m_nInList <= 0)
{
return;
}
GameStartPoint* pGSP = DNULL;
ObjectLink* pLink = pList->m_pFirstLink;
// For a multiplayer game, just get a random startpoint
if(g_pBloodServerShell->GetGameType() != GAMETYPE_SINGLE)
{
int nStartPoint = pServerDE->IntRandom(0, pList->m_nInList - 1);
for (int i=0; i < nStartPoint; i++)
{
pLink = pLink->m_pNext;
}
pGSP = (GameStartPoint*)pServerDE->HandleToObject(pLink->m_hObject);
// For team-based games, find a start point for our team...
if (g_pBloodServerShell->IsMultiplayerTeamBasedGame())
{
int nSafety = pList->m_nInList;
while (pGSP && pGSP->GetTeamID() != (int)GetTeamID() && pGSP->GetTeamID() != 0)
{
pLink = pLink->m_pNext;
if (!pLink) pLink = pList->m_pFirstLink;
if (pLink)
{
pGSP = (GameStartPoint*)pServerDE->HandleToObject(pLink->m_hObject);
}
else
{
pGSP = NULL;
}
if (--nSafety < 0)
{
pGSP = NULL;
}
}
if (!pGSP)
{
pLink = pList->m_pFirstLink;
if (pLink) pGSP = (GameStartPoint*)pServerDE->HandleToObject(pLink->m_hObject);
}
}
}
else // Single player, go to a named startpoint, if it exists
{
DBOOL bRemoveString = DFALSE;
GameStartPoint *pGSPSingle = DNULL;
HSTRING hstrStartPoint = g_pBloodServerShell->GetStartPointName();
if (!hstrStartPoint)
{
bRemoveString = DTRUE;
hstrStartPoint = pServerDE->CreateString("start");
}
pGSP = DNULL;
for (int i=0; i < pList->m_nInList; i++)
{
pGSP = (GameStartPoint*)pServerDE->HandleToObject(pLink->m_hObject);
if (!pGSP->IsMultiplayer())
{
// save it just in case
pGSPSingle = pGSP;
if (pServerDE->CompareStringsUpper(hstrStartPoint, pGSP->GetName()))
{
break;
}
}
pLink = pLink->m_pNext;
pGSP = DNULL;
}
if( bRemoveString )
pServerDE->FreeString( hstrStartPoint );
// Couldn't find a named startpoint, try to use any single player
if (!pGSP && pGSPSingle) pGSP = pGSPSingle;
}
DRotation rRot;
ROT_INIT(rRot);
if (pGSP)
{
// Set the rotation..
m_fYaw = pGSP->GetPitchYawRoll().y;
m_fPitch = 0.0f;
HOBJECT hGSP = pServerDE->ObjectToHandle((LPBASECLASS)pGSP);
pServerDE->GetObjectPos(hGSP, &pos);
// Send any trigger message this is supposed to cause
pGSP->SendTrigger();
}
pServerDE->TeleportObject(m_hObject, &pos);
SendMessageToClient(SMSG_FORCEROTATION);
MoveObjectToGround(m_hObject);
pServerDE->RelinquishList(pList);
UpdateClientPhysics(); // (to make sure they have their model around)
TeleportClientToServerPos();
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::ValidateAttributes()
//
// PURPOSE: Make sure that the player's attributes are within valid ranges
//
// --------------------------------------------------------------------------- //
void CPlayerObj::ValidateAttributes()
{
CServerDE* pServerDE = GetServerDE();
m_nCharacter = DCLAMP(m_nCharacter, 0, MAX_CHARACTER);
m_nSkin = DCLAMP(m_nSkin, MULTIPLAY_SKIN_MIN, MULTIPLAY_SKIN_MAX);
m_nAttribStrength = DCLAMP(m_nAttribStrength, 1, 5);
m_nAttribSpeed = DCLAMP(m_nAttribSpeed, 1, 5);
m_nAttribResistance = DCLAMP(m_nAttribResistance, 1, 5);
m_nAttribMagic = DCLAMP(m_nAttribMagic, 1, 5);
if ((m_nAttribStrength + m_nAttribSpeed + m_nAttribResistance + m_nAttribMagic) > MAX_ATTRIBUTES)
{
HSTRING hstr = pServerDE->FormatString(IDS_GENERAL_ATTRIBHIGH);
SendConsoleMessage(pServerDE->GetStringData(hstr));
pServerDE->FreeString(hstr);
// Attribute maximums exceeded
m_nAttribStrength = DEFAULT_ATTRIBUTE;
m_nAttribSpeed = DEFAULT_ATTRIBUTE;
m_nAttribResistance = DEFAULT_ATTRIBUTE;
m_nAttribMagic = DEFAULT_ATTRIBUTE;
}
m_InventoryMgr.SetStrength(m_nAttribStrength + m_nBindingStrength);
m_InventoryMgr.SetMagic(m_nAttribMagic + m_nBindingMagic);
m_damage.CalculateResistance(m_nAttribResistance + m_nBindingResistance);
SetMoveVel(gMoveVel[m_nAttribSpeed-1]);
SetJumpVel(DEFAULT_JUMPVEL);
m_PStateChangeFlags = PSTATE_ALL;
// m_InventoryMgr.SetFullAmmo();
/*
if (m_bBindingBlending)
pServerDE->SetObjectColor(m_hObject, 0.0f, 0.0f, 0.0f, ALPHA_CLOAKED);
if (m_bBindingConstitution)
{
m_damage.SetHitPoints(150);
m_damage.SetMaxHitPoints(150);
}
if (m_bBindingIncreasedDamage)
{
m_InventoryMgr.AddDamageMultiplier(BINDING_INCREASE_DAMAGE_AMT);
}
if (m_bBindingQuickness)
{
m_InventoryMgr.AddFireRateMultiplier(BINDING_QUICKNESS_FACTOR);
}
*/
// Set attributes
m_damage.SetMaxHitPoints(g_fMaxHealth[m_nAttribStrength-1]);
m_damage.SetMaxMegaHitPoints(g_fMaxMegaHealth[m_nAttribStrength-1]);
m_damage.SetMaxArmorPoints(g_fMaxArmor[m_nAttribMagic-1]);
m_damage.SetMaxNecroArmorPoints(g_fMaxMegaArmor[m_nAttribMagic-1]);
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::SetCharacter
//
// PURPOSE: Sets filenames to refer to the current character.
//
// --------------------------------------------------------------------------- //
void CPlayerObj::SetCharacter(DBYTE nCharacter)
{
CServerDE* pServerDE = GetServerDE();
if (nCharacter > MAX_CHARACTER) return;
m_nCharacter = nCharacter;
pServerDE->SetModelFilenames(m_hObject,
gCharacterValues[m_nCharacter].szModelName,
gCharacterSkins[m_nCharacter][m_nSkin]);
m_PStateChangeFlags |= PSTATE_MODELFILENAMES;
// Init the animations
m_Anim_Sound.SetAnimationIndexes(m_hObject);
m_Anim_Sound.GenerateHitSpheres(m_hObject);
sprintf(msgbuf, "sounds\\chosen\\%s", gCharacterValues[m_nCharacter].szName);
m_Anim_Sound.SetSoundRoot(msgbuf);
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::ObjectTouch()
//
// PURPOSE: Called when the player is touching another TouchNotify object.
//
// --------------------------------------------------------------------------- //
void CPlayerObj::ObjectTouch(HOBJECT hObj, DFLOAT fData)
{
CServerDE* pServerDE = GetServerDE();
DBOOL bDoFallingDamage;
// Hack to see if we are being pushed by a rotating door. If so, set velocity back
if( hObj )
{
HCLASS hObjClass = pServerDE->GetObjectClass( hObj );
HCLASS hDoorClass = pServerDE->GetClass( "RotatingDoor" );
if ( pServerDE->IsKindOf( hObjClass, hDoorClass ) && !m_bDoorPush )
{
RotatingDoor *pRotDoor = (RotatingDoor*)pServerDE->HandleToObject(hObj);
if( pRotDoor && pRotDoor->GetDoorState() == DOORSTATE_OPENING && pRotDoor->CanPushPlayerBack())
{
// Get my vectors
DRotation rRot;
DVector vF, vU, vR;
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
// Set some backwards velocity to the player to try to move him out of the way
VEC_MULSCALAR(m_vDoorPush, vF, -500.0f);
m_bDoorPush = DTRUE;
// pServerDE->SetVelocity(m_hObject, &vF);
return;
}
}
}
bDoFallingDamage = DTRUE;
if( g_pBloodServerShell->IsMultiplayerGame( ))
{
if( !g_pBloodServerShell->GetNetGameInfo( )->m_bFallDamage )
bDoFallingDamage = DFALSE;
}
/*
if (fData >= PA_MIN_DAMAGE_FORCE && bDoFallingDamage )
{
pServerDE->BPrint("impact force=%f", fData);
// Damage myself
DVector vFall, vPos;
VEC_SET(vFall, 0.0f, -1.0f, 0.0f);
DFLOAT fDamage;
// Set some minimum guidelines
if (m_bFalling && (pServerDE->GetTime() - m_startFall) >= 2.0f)
{
fDamage = (fData - PA_MIN_DAMAGE_FORCE) / 25;
pServerDE->GetObjectPos(m_hObject, &vPos);
DamageObject(m_hObject, this, m_hObject, fDamage, vFall, vPos, DAMAGE_TYPE_NORMAL);
}
}
*/
DVector vCurVel;
pServerDE->GetVelocity(m_hObject, &vCurVel);
if (bDoFallingDamage )
{
// Damage myself
// Set some minimum guidelines
if ((m_bFalling || m_bServerFalling) && vCurVel.y < -1100.0f)
{
DVector vFall, vPos;
VEC_SET(vFall, 0.0f, -1.0f, 0.0f);
DFLOAT fDamage;
fDamage = (fData - PA_MIN_DAMAGE_FORCE) / 25;
if (fDamage > 0)
{
pServerDE->GetObjectPos(m_hObject, &vPos);
DamageObject(m_hObject, this, m_hObject, fDamage, vFall, vPos, DAMAGE_TYPE_NORMAL);
}
}
}
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CPlayerObj::ObjectCrush()
//
// PURPOSE: Called when the player is touching another TouchNotify object.
//
// --------------------------------------------------------------------------- //
void CPlayerObj::ObjectCrush(HOBJECT hObj, DFLOAT fData)
{
CServerDE* pServerDE = GetServerDE();
// if we are being crushed by a rotating door, tell it to stop moving.
if (hObj)
{
HCLASS hObjClass = pServerDE->GetObjectClass( hObj );
HCLASS hDoorClass = pServerDE->GetClass( "RotatingDoor" );
if ( pServerDE->IsKindOf( hObjClass, hDoorClass ))
{
RotatingDoor *pRotDoor = (RotatingDoor*)pServerDE->HandleToObject(hObj);
if (pRotDoor->GetDoorState() == DOORSTATE_OPENING)
{
// Send the message back to the RotatingDoor
HMESSAGEWRITE hMessage = pServerDE->StartMessageToObject(this, hObj, MID_DOORBLO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -