bool CombatManager::handleAttack(CreatureObject* attacker, uint64 targetId, ObjectControllerCmdProperties *cmdProperties) { CreatureObject* defender = dynamic_cast<CreatureObject*>(gWorldManager->getObjectById(targetId)); // get the current weapon //what if he/she/it is left handed ? what if he she it has multiple appendages with weapons ? Weapon* weapon = dynamic_cast<Weapon*>(gWorldManager->getObjectById(attacker->GetWeaponId())); //auto weapon = dynamic_cast<Weapon*>(gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::equipment::EquipmentService>("EquipmentService")->GetEquippedObject(attacker, "hold_r")); if (!weapon) { return(false); } if (!defender) { return(false); } // NOTE: Some weapon data just for tesing and to give the npc a fair chance... uint32 weaponGroup = weapon->getGroup(); float weaponRange = 6.0; //if (weaponGroup <= WeaponGroup_Polearm) //{ // weaponRange = 6.0; //} // else if (weaponGroup == WeaponGroup_Rifle) { weaponRange = 64.0; } else if (weaponGroup == WeaponGroup_Pistol) { weaponRange = 35.0; } else if (weaponGroup == WeaponGroup_Carbine) { weaponRange = 50.0; } //else //{ // weaponRange = 6.0; //} // if we are out of range, skip this attack. if (glm::distance(attacker->mPosition, defender->mPosition) > weaponRange) { // Target out of range. PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker); if (playerAttacker && playerAttacker->isConnected()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "target_out_of_range"), playerAttacker); } // It's like you shoot but missed, maintain cooldown. // return true; return false; } if(_verifyCombatState(attacker,defender->getId())) { // Execute the attack /*uint8 attackResult = */_executeAttack(attacker,defender,cmdProperties,weapon); return(true); } return(false); }
bool CombatManager::_verifyCombatState(CreatureObject* attacker, uint64 defenderId) { PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker); CreatureObject* defender = dynamic_cast<CreatureObject*>(gWorldManager->getObjectById(defenderId)); if (!defender) { // No such object. return(false); } // Do not try to attack already incapped or dead objects. if (defender->isIncapacitated() || defender->isDead()) { return false; } //Do not attack if we are incapped or already dead or mounted. if (attacker->isIncapacitated() || attacker->isDead() || playerAttacker->checkIfMounted()) { return false; } // make sure we got both objects if (playerAttacker && defender) { //Do not attack if we are mounted if(playerAttacker->checkIfMounted()) { return false; } // if our target is a player, he must be dueling us or both need to be overt(TODO) if (PlayerObject* defenderPlayer = dynamic_cast<PlayerObject*>(defender)) { // also return, if our target is incapacitated or dead if(!playerAttacker->checkDuelList(defenderPlayer) || !defenderPlayer->checkDuelList(playerAttacker) || defenderPlayer == playerAttacker) { return(false); } if(defenderPlayer->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if(defenderPlayer->isDead()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead"); return(false); } // put us in combat state gStateManager.setCurrentActionState(attacker, CreatureState_Combat); gStateManager.setCurrentActionState(attacker, CreatureState_CombatAttitudeNormal); // put our target in combat state if(!defenderPlayer->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(defender, CreatureState_Combat); gStateManager.setCurrentActionState(defender, CreatureState_CombatAttitudeNormal); } // update our defender list if (!playerAttacker->checkDefenderList(defenderPlayer->getId())) { playerAttacker->AddDefender(defenderPlayer->getId()); } // update our targets defender list if (!defenderPlayer->checkDefenderList(playerAttacker->getId())) { playerAttacker->AddDefender(defenderPlayer->getId()); } if (!defenderPlayer->autoAttackEnabled()) { // Player can/may start auto-attack if idle. defenderPlayer->getController()->enqueueAutoAttack(playerAttacker->getId()); } } else { // our target is a creature if (defender->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if (defender->isDead()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead"); return(false); } // Vefify that out target is attackable. It's not nice to spam attacks at innocent npc's. if (!(defender->getPvPStatus() & CreaturePvPStatus_Attackable)) { return(false); } // put us in combat state // if (!playerAttacker->states.checkState((CreatureState)(CreatureState_Combat + CreatureState_CombatAttitudeNormal))) { // playerAttacker->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable + CreaturePvPStatus_Aggressive + CreaturePvPStatus_Enemy)); gMessageLib->sendUpdatePvpStatus(playerAttacker,playerAttacker, playerAttacker->getPvPStatus() | CreaturePvPStatus_Attackable); // TEST STATE MANAGER! gStateManager.setCurrentActionState(attacker, CreatureState_Combat); gStateManager.setCurrentActionState(attacker, CreatureState_CombatAttitudeNormal); } if (!defender->states.checkState((CreatureState_Combat))) { // Creature was NOT in combat before, and may very well be dormant. // Wake him up. gWorldManager->forceHandlingOfDormantNpc(defender->getId()); gWorldManager->forceHandlingOfReadyNpc(defender->getId()); // Creature may need some aggro built up before going into combat state?? gStateManager.setCurrentActionState(defender, CreatureState_Combat); gStateManager.setCurrentActionState(defender, CreatureState_CombatAttitudeNormal); } gMessageLib->sendUpdatePvpStatus(defender, playerAttacker, defender->getPvPStatus() | CreaturePvPStatus_Attackable | CreaturePvPStatus_Enemy); // update our defender list if (!playerAttacker->checkDefenderList(defender->getId())) { playerAttacker->AddDefender(defenderPlayer->getId()); } // update our targets defender list if (!defender->checkDefenderList(playerAttacker->getId())) { playerAttacker->AddDefender(defenderPlayer->getId()); } } } else { return(false); } return(true); }
//====================================================================================================================== // // create tangible // bool MessageLib::sendCreateTangible(TangibleObject* tangibleObject,PlayerObject* targetObject, bool sendchildren) { if(!_checkPlayer(targetObject)) { gLogger->log(LogManager::DEBUG,"MessageLib::sendCreateTangible No valid player"); return(false); } if(ResourceContainer* resContainer = dynamic_cast<ResourceContainer*>(tangibleObject)) { return sendCreateResourceContainer(resContainer,targetObject); } else if(FactoryCrate* crate = dynamic_cast<FactoryCrate*>(tangibleObject)) { return sendCreateFactoryCrate(crate,targetObject); } else if(tangibleObject->getTangibleGroup() == TanGroup_Static) { return sendCreateStaticObject(tangibleObject,targetObject); } uint64 parentId = tangibleObject->getParentId(); sendCreateObjectByCRC(tangibleObject,targetObject,false); if(parentId != 0) { // its in a cell, container, inventory if(parentId != targetObject->getId()) { // could be inside a crafting tool Object* parent = gWorldManager->getObjectById(parentId); CreatureObject* parentObject = dynamic_cast<CreatureObject*>(parent); if(parent && dynamic_cast<CraftingTool*>(parent)) { sendContainmentMessage(tangibleObject->getId(),parentId,0,targetObject); } // if equipped, also tie it to the object else if(parentObject) { Item* item = dynamic_cast<Item*>(tangibleObject); sendContainmentMessage(tangibleObject->getId(),parentObject->getId(),4,targetObject); } else { sendContainmentMessage(tangibleObject->getId(),tangibleObject->getParentId(),0xffffffff,targetObject); } } // or tied directly to an object else { sendContainmentMessage(tangibleObject->getId(),tangibleObject->getParentId(),4,targetObject); } } else { sendContainmentMessage(tangibleObject->getId(),tangibleObject->getParentId(),0xffffffff,targetObject); } sendBaselinesTANO_3(tangibleObject,targetObject); sendBaselinesTANO_6(tangibleObject,targetObject); //now check whether we have children!!! ObjectIDList* ol = tangibleObject->getObjects(); ObjectIDList::iterator it = ol->begin(); while(it != ol->end()) { TangibleObject* tO = dynamic_cast<TangibleObject*>(gWorldManager->getObjectById((*it))); if(!tO) { gLogger->log(LogManager::DEBUG,"MessageLib::sendCreateTangible::Unable to find object with ID %PRIu64", (*it)); it++; continue; } PlayerObject* player = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(targetObject->getId())); //for children add knownPlayers!!!! //tO->addKnownObjectSafe(player); //player->addKnownObjectSafe(tO); sendCreateObject(tO,player,false); it++; } sendEndBaselines(tangibleObject->getId(),targetObject); return(true); }
bool NpcManager::_verifyCombatState(CreatureObject* attacker, uint64 defenderId) { if (!attacker || !defenderId) { return false; } CreatureObject* defender = dynamic_cast<CreatureObject*>(gWorldManager->getObjectById(defenderId)); if (!defender) { return false; } // If the target (defender) do have me in his defender list, we should not bother. /* if (defender->checkDefenderList(attacker->getId())) { return true; } */ PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker); // make sure we got both objects if (playerAttacker && defender) { // if our target is a player, he must be dueling us or both need to be overt(TODO) if (PlayerObject* defenderPlayer = dynamic_cast<PlayerObject*>(defender)) { // also return, if our target is incapacitated or dead if(!playerAttacker->checkDuelList(defenderPlayer) || !defenderPlayer->checkDuelList(playerAttacker) || defenderPlayer == playerAttacker) { return(false); } if(defenderPlayer->GetCreature()->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if(defenderPlayer->GetCreature()->isDead()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead"); return(false); } // put us in combat state if(!playerAttacker->GetCreature()->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(playerAttacker->GetCreature(),CreatureState_Combat); gStateManager.setCurrentActionState(playerAttacker->GetCreature(),CreatureState_CombatAttitudeNormal); } // put our target in combat state if(!defenderPlayer->GetCreature()->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_Combat); gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_CombatAttitudeNormal); } // update our defender list if (!playerAttacker->GetCreature()->checkDefenderList(defenderPlayer->getId())) // or if (!playerAttacker->checkDefenderList(defenderId) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } // update our targets defender list if (!defenderPlayer->GetCreature()->checkDefenderList(playerAttacker->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } } else { // our target is a creature if (defender->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if (defender->isDead()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead"); return(false); } // Vefify that our target is attackable. It's not nice to spam attacks at innocent npc's. if (!(defender->getPvPStatus() & CreaturePvPStatus_Attackable)) { return(false); } // put us in combat state if (!playerAttacker->GetCreature()->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(playerAttacker->GetCreature(),CreatureState_Combat); gStateManager.setCurrentActionState(playerAttacker->GetCreature(),CreatureState_CombatAttitudeNormal); } // put our target in combat state if (!defender->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(defender,CreatureState_Combat); gStateManager.setCurrentActionState(defender,CreatureState_CombatAttitudeNormal); } // update our defender list if (!playerAttacker->GetCreature()->checkDefenderList(defender->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } // update our targets defender list if (!defender->checkDefenderList(playerAttacker->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } } return(true); } else if (AttackableCreature* attackerNpc = dynamic_cast<AttackableCreature*>(attacker)) { // make sure we got both objects if (attackerNpc && defender) { // Our target can be a player or another npc. if (PlayerObject* defenderPlayer = dynamic_cast<PlayerObject*>(defender)) { // The target (defender) is a player. Kill him! if (defenderPlayer->GetCreature()->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if(defenderPlayer->GetCreature()->isDead()) { return(false); } /* if (!defenderPlayer->checkPvPState(CreaturePvPStatus_Attackable)) { // Player is not attackable return(false); } */ // put us in combat state if (!attackerNpc->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(attackerNpc,CreatureState_Combat); gStateManager.setCurrentActionState(attackerNpc,CreatureState_CombatAttitudeNormal); } // put our target in combat stance if (!defenderPlayer->GetCreature()->states.checkState(CreatureState_Combat)) { gMessageLib->sendUpdatePvpStatus(defenderPlayer->GetCreature(),defenderPlayer, defenderPlayer->GetCreature()->getPvPStatus() | CreaturePvPStatus_Attackable | CreaturePvPStatus_Aggressive); // | CreaturePvPStatus_Enemy); gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_Combat); gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_CombatAttitudeNormal); } // If the target (defender) is not on our list, update pvp-status. if (!attackerNpc->checkDefenderList(defenderPlayer->getId())) { // May not be neeeded, since the pvp-status is changed when getting enough aggro. // gMessageLib->sendUpdatePvpStatus(attackerNpc,defenderPlayer, attackerNpc->getPvPStatus() | CreaturePvPStatus_Attackable | CreaturePvPStatus_Aggressive | CreaturePvPStatus_Enemy); // update our defender list playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); // Update player and all his group mates currently in range. /* PlayerList inRangeMembers = defenderPlayer->getInRangeGroupMembers(true); PlayerList::iterator it = inRangeMembers.begin(); while (it != inRangeMembers.end()) { PlayerObject* player = (*it); // If player online, send emote. if (player && player->isConnected()) { MessageLib->sendUpdatePvpStatus(attackerNpc,player); } } */ } // update our targets defender list if (!defenderPlayer->GetCreature()->checkDefenderList(attackerNpc->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } // Player can/may start auto-attack if idle. if (!defenderPlayer->autoAttackEnabled()) { defenderPlayer->getController()->enqueueAutoAttack(attackerNpc->getId()); } } else if (dynamic_cast<AttackableCreature*>(defender)) { // The target (defender) is a npc. Kill him! // Here I think some validation would be great, don't wanna kill you piket-brother? if (defenderPlayer->GetCreature()->isIncapacitated()) { // gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap"); return(false); } else if(defenderPlayer->GetCreature()->isDead()) { return(false); } // put us in combat state if (!attackerNpc->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(attackerNpc,CreatureState_Combat); gStateManager.setCurrentActionState(attackerNpc,CreatureState_CombatAttitudeNormal); } // put our target in combat state if (!defenderPlayer->GetCreature()->states.checkState(CreatureState_Combat)) { gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_Combat); gStateManager.setCurrentActionState(defenderPlayer->GetCreature(),CreatureState_CombatAttitudeNormal); } // update our defender list if (!attackerNpc->checkDefenderList(defenderPlayer->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } // update our targets defender list if (!defenderPlayer->GetCreature()->checkDefenderList(attackerNpc->getId())) { playerAttacker->GetCreature()->AddDefender(defenderPlayer->getId()); } } return(true); } return(false); } return false; }
void WorldManager::destroyObject(Object* object) { switch(object->getType()) { case ObjType_Player: { //destroys knownObjects in the destructor PlayerObject* player = dynamic_cast<PlayerObject*>(object); // moved most of the code to the players destructor // onPlayerLeft event, notify scripts string params; params.setLength(sprintf(params.getAnsi(),"%s %s %u",getPlanetNameThis(),player->getFirstName().getAnsi(),static_cast<uint32>(mPlayerAccMap.size()))); mWorldScriptsListener.handleScriptEvent("onPlayerLeft",params); // gLogger->logMsg("WorldManager::destroyObject: Player Client set to NULL"); delete player->getClient(); player->setClient(NULL); player->setConnectionState(PlayerConnState_Destroying); } break; case ObjType_NPC: case ObjType_Creature: { CreatureObject* creature = dynamic_cast<CreatureObject*>(object); // remove any timers we got running removeCreatureHamToProcess(creature->getHam()->getTaskId()); // remove from cell / SI if (!object->getParentId()) { // Not all objects-creatures of this type are points. if(creature->getSubZoneId()) { if(QTRegion* region = getQTRegion(creature->getSubZoneId())) { creature->setSubZoneId(0); region->mTree->removeObject(creature); } } else { mSpatialIndex->RemovePoint(object->getId(),object->mPosition.x,object->mPosition.z); } } else { if(CellObject* cell = dynamic_cast<CellObject*>(getObjectById(object->getParentId()))) { cell->removeObject(object); } else { //gLogger->logMsgF("WorldManager::destroyObject: couldn't find cell %"PRIu64"",MSG_HIGH,object->getParentId()); } } // destroy known objects object->destroyKnownObjects(); // if its a shuttle, remove it from the shuttle list if(creature->getCreoGroup() == CreoGroup_Shuttle) { ShuttleList::iterator shuttleIt = mShuttleList.begin(); while(shuttleIt != mShuttleList.end()) { if((*shuttleIt)->getId() == creature->getId()) { mShuttleList.erase(shuttleIt); break; } ++shuttleIt; } } } break; case ObjType_Structure: { // cave what do we do with player cities ?? // then the parent Id should be the region object. shouldnt it???? if(object->getSubZoneId()) { if(QTRegion* region = getQTRegion(object->getSubZoneId())) { object->setSubZoneId(0); region->mTree->removeObject(object); } } else { mSpatialIndex->RemovePoint(object->getId(),object->mPosition.x,object->mPosition.z); } object->destroyKnownObjects(); //remove it out of the worldmanagers structurelist now that it is deleted ObjectIDList::iterator itStruct = mStructureList.begin(); while(itStruct != mStructureList.end()) { if((*itStruct)==object->getId()) itStruct = mStructureList.erase(itStruct); else itStruct++; } } break; case ObjType_Building: { BuildingObject* building = dynamic_cast<BuildingObject*>(object); if(building) { if(object->getSubZoneId()) { if(QTRegion* region = getQTRegion(object->getSubZoneId())) { object->setSubZoneId(0); region->mTree->removeObject(object); } } else { //mSpatialIndex->InsertRegion(key,building->mPosition.x,building->mPosition.z,building->getWidth(),building->getHeight()); mSpatialIndex->RemoveRegion(object->getId(),object->mPosition.x-building->getWidth(),object->mPosition.z-building->getHeight(),object->mPosition.x+building->getWidth(),object->mPosition.z+building->getHeight()); } //remove it out of the worldmanagers structurelist now that it is deleted ObjectIDList::iterator itStruct = mStructureList.begin(); while(itStruct != mStructureList.end()) { if((*itStruct)==object->getId()) itStruct = mStructureList.erase(itStruct); else itStruct++; } } else gLogger->logMsgF("WorldManager::destroyObject: nearly did not remove: %"PRIu64"s knownObjectList",MSG_HIGH,object->getId()); object->destroyKnownObjects(); } break; case ObjType_Cell: { //a cell shouldnt have knownobjects ... -that should be checked to make sure it is true object->destroyKnownObjects(); } break; case ObjType_Tangible: { if(TangibleObject* tangible = dynamic_cast<TangibleObject*>(object)) { uint64 parentId = tangible->getParentId(); if(parentId == 0) { mSpatialIndex->RemovePoint(tangible->getId(),tangible->mPosition.x,tangible->mPosition.z); } else { if(CellObject* cell = dynamic_cast<CellObject*>(getObjectById(parentId))) { cell->removeObject(object); } else { // Well, Tangible can have more kind of parents than just cells or SI. For example players or Inventory. // the tangible is owned by its containing object (please note exeption of inventory / player with equipped stuff) // however we should leave the object link in the worldmanagers Objectmap and only store references in the object // we will have great trouble finding items otherwise //gLogger->logMsgF("WorldManager::destroyObject couldn't find cell %"PRIu64"",MSG_NORMAL,parentId); } } } else { gLogger->logMsgF("WorldManager::destroyObject: error removing : %"PRIu64"",MSG_HIGH,object->getId()); } // destroy known objects object->destroyKnownObjects(); } break; case ObjType_Region: { RegionMap::iterator it = mRegionMap.find(object->getId()); if(it != mRegionMap.end()) { mRegionMap.erase(it); } else { gLogger->logMsgF("Worldmanager::destroyObject: Could not find region %"PRIu64"",MSG_NORMAL,object->getId()); } //camp regions are in here, too QTRegionMap::iterator itQ = mQTRegionMap.find(static_cast<uint32>(object->getId())); if(itQ != mQTRegionMap.end()) { mQTRegionMap.erase(itQ); gLogger->logMsgF("Worldmanager::destroyObject: qt region %"PRIu64"",MSG_HIGH,object->getId()); } object->destroyKnownObjects(); } break; case ObjType_Intangible: { gLogger->logMsgF("Object of type ObjType_Intangible almost UNHANDLED in WorldManager::destroyObject:",MSG_HIGH); // intangibles are controllers / pets in the datapad // they are NOT in the world //we really shouldnt have any of thoose object->destroyKnownObjects(); } break; default: { gLogger->logMsgF("Unhandled ObjectType in WorldManager::destroyObject: %u",MSG_HIGH,(uint32)(object->getType())); // Please, when adding new stufff, at least take the time to add a stub for that type. // Better fail always, than have random crashes. assert(false && "WorldManager::destroyObject Unhandled ObjectType"); } break; } object->destroyKnownObjects(); // finally delete it ObjectMap::iterator objMapIt = mObjectMap.find(object->getId()); if(objMapIt != mObjectMap.end()) { mObjectMap.erase(objMapIt); } else { gLogger->logMsgF("WorldManager::destroyObject: error removing from objectmap: %"PRIu64"",MSG_HIGH,object->getId()); } }