void ObjectController::_handleDismissGroupMember(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); // make sure its a fully grouped player if(player->getGroupId() == 0) { return; } // lets get the target player message->setIndex(32); PlayerObject* targetPlayer = dynamic_cast<PlayerObject*>(gWorldManager->getObjectById(message->getUint64())); // if target is valid if(targetPlayer == NULL || targetPlayer->getGroupId() != player->getGroupId()) { gMessageLib->sendSystemMessage(player,L"Invalid Target."); return; } // we advise the chat server about it Message* newMessage; gMessageFactory->StartMessage(); gMessageFactory->addUint32(opIsmGroupDismissGroupMember); gMessageFactory->addUint32(targetPlayer->getAccountId()); newMessage = gMessageFactory->EndMessage(); player->getClient()->SendChannelA(newMessage,player->getAccountId(),CR_Chat,2); }
bool WorldManager::_handleDisconnectUpdate(uint64 callTime,void* ref) { PlayerList::iterator it = mPlayersToRemove.begin(); while(it != mPlayersToRemove.end()) { PlayerObject* playerObject = (*it); // we timed out, so save + remove it if(--*(playerObject->getDisconnectTime()) <= 0 && playerObject->isLinkDead()) { // reset link dead state playerObject->togglePlayerFlagOff(PlayerFlag_LinkDead); playerObject->setConnectionState(PlayerConnState_Destroying); //remove the player out of his group - if any GroupObject* group = gGroupManager->getGroupObject(playerObject->getGroupId()); if(group) { group->removePlayer(playerObject->getId()); } //asynch save savePlayer(playerObject->getAccountId(),true,WMLogOut_LogOut); it = mPlayersToRemove.erase(it); } else ++it; } return(true); }
void ObjectController::_handleTeach(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { // check if our attribute targetplayer exists // check if our target is a player // parse the string if a known skill was selected // check what skills we can teach // check which of these skills the target might learn PlayerObject* teacherObject = dynamic_cast<PlayerObject*>(mObject); PlayerObject* pupilObject = dynamic_cast<PlayerObject*> (teacherObject->getTarget()); // check if we have a target if(!pupilObject ) { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","no_target"); return; } if(pupilObject == teacherObject) { // target self:( gMessageLib->sendSystemMessage(teacherObject,L"","teaching","no_teach_self"); return; } if((teacherObject->getGroupId() == 0)||(teacherObject->getGroupId() != pupilObject ->getGroupId())) { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","not_in_same_group","","",L"",0,"","",L"",pupilObject->getId()); return; } //check if our pupil already gets taught if (!pupilObject->getTrade()->getTeacher()) { pupilObject->getTrade()->setTeacher(teacherObject); gSkillManager->teach(pupilObject,teacherObject,""); } else { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","student_has_offer_to_learn","","",L"",0,"","",L"",pupilObject->getId()); } }
void ObjectController::_handleGroupChat(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); string msgText; msgText.setType(BSTRType_Unicode16); msgText.setLength(512); //Honey bunnies! //this is like all handled by the Objectcontroller??? //we just have to look at the Message here !!!!!!!! //gLogger->hexDump always shows the complete Message!!!!! the Objectcontroller however sets the Index to the first data //byte AFTER the Objectcontroller header has been dealt with ! /* data32 = message->getUint32(); // object controller opcode data32 = message->getUint32(); // Unknown data32 = message->getUint32(); // command enqueue playerId = message->getUint64();// player id data32 = message->getUint32(); // Unknown uint32 requestId = message->getUint32(); // RequestID // data32 = message->getUint32(); // Unknown RequestID????? data32 = message->getUint32(); // command crc (crc of "groupchat") data64 = message->getUint64(); // empty id field */ message->getStringUnicode16(msgText); // unicode string // make sure its a fully grouped player if (!player) { gLogger->logMsg("ObjectController::_handleGroupChat NO PLAYER\n"); } if(!player->getGroupId()) { gLogger->logMsg("ObjectController::_handleGroupChat NO GROUP"); } // let the chatserver handle this. Message* newMessage; gMessageFactory->StartMessage(); gMessageFactory->addUint32(opIsmGroupSay); gMessageFactory->addUint32(0); gMessageFactory->addString(msgText); newMessage = gMessageFactory->EndMessage(); player->getClient()->SendChannelA(newMessage,player->getAccountId(),CR_Chat,2); //this should be fastpath as not being Mission critical and we want to prevent the communication protocol overhead with Acks and resends // Convert since we are going to print it. // msgText.convert(BSTRType_ANSI); }
void ObjectController::_handleLeaveGroup(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); if(player->getGroupId() == 0) { return; } // we advise the chat server about it gMessageLib->sendIsmGroupLeave(player); }
void ObjectController::_handleDisband(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); if(player->getGroupId() == 0) { return; } // we advise the chat server about the disband Message* newMessage; gMessageFactory->StartMessage(); gMessageFactory->addUint32(opIsmGroupDisband); newMessage = gMessageFactory->EndMessage(); player->getClient()->SendChannelA(newMessage,player->getAccountId(),CR_Chat,2); }
void WorldManager::savePlayerSync(uint32 accId,bool remove) { PlayerObject* playerObject = getPlayerByAccId(accId); Ham* ham = playerObject->getHam(); mDatabase->destroyResult(mDatabase->executeSynchSql("UPDATE characters SET parent_id=%"PRIu64",oX=%f,oY=%f,oZ=%f,oW=%f,x=%f,y=%f,z=%f,planet_id=%u WHERE id=%"PRIu64"",playerObject->getParentId() ,playerObject->mDirection.x,playerObject->mDirection.y,playerObject->mDirection.z,playerObject->mDirection.w ,playerObject->mPosition.x,playerObject->mPosition.y,playerObject->mPosition.z ,mZoneId,playerObject->getId())); mDatabase->destroyResult(mDatabase->executeSynchSql("UPDATE character_attributes SET health_current=%u,action_current=%u,mind_current=%u" ",health_wounds=%u,strength_wounds=%u,constitution_wounds=%u,action_wounds=%u,quickness_wounds=%u" ",stamina_wounds=%u,mind_wounds=%u,focus_wounds=%u,willpower_wounds=%u,battlefatigue=%u,posture=%u,moodId=%u,title=\'%s\'" ",character_flags=%u,states=%"PRIu64",language=%u, group_id=%"PRIu64" WHERE character_id=%"PRIu64"", ham->mHealth.getCurrentHitPoints() - ham->mHealth.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mAction.getCurrentHitPoints() - ham->mAction.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mMind.getCurrentHitPoints() - ham->mMind.getModifier(), //Llloydyboy Added the -Modifier so that when buffs are reinitialised, it doesn't screw up HAM ham->mHealth.getWounds(), ham->mStrength.getWounds(), ham->mConstitution.getWounds(), ham->mAction.getWounds(), ham->mQuickness.getWounds(), ham->mStamina.getWounds(), ham->mMind.getWounds(), ham->mFocus.getWounds(), ham->mWillpower.getWounds(), ham->getBattleFatigue(), playerObject->states.getPosture(), playerObject->getMoodId(), playerObject->getTitle().getAnsi(), playerObject->getPlayerFlags(), playerObject->states.getAction(), playerObject->getLanguage(), playerObject->getGroupId(), playerObject->getId())); gBuffManager->SaveBuffs(playerObject, GetCurrentGlobalTick()); if(remove) destroyObject(playerObject); }
void ObjectController::_handleGroupLootMode(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { // disabled for now //return; gLogger->logMsg("_handleGroupLootMode"); PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); // make sure its a fully grouped player if(player->getGroupId() == 0) { return; } // we advise the chat server about it Message* newMessage; gMessageFactory->StartMessage(); gMessageFactory->addUint32(opIsmGroupLootModeRequest); newMessage = gMessageFactory->EndMessage(); player->getClient()->SendChannelA(newMessage,player->getAccountId(),CR_Chat,2); }
uint8 CombatManager::_executeAttack(CreatureObject* attacker,CreatureObject* defender,ObjectControllerCmdProperties *cmdProperties,Weapon* weapon) { uint8 randomHitPool = 100; //uint8 randomPoolHitChance = 100; uint8 stateApplied = 0; int32 multipliedDamage = 0; BString combatSpam = "melee"; // first see if we actually hit our target uint8 attackResult = _hitCheck(attacker,defender,cmdProperties,weapon); // only proceed, if so if(!attackResult) { // TODO: retrieve from weapon int32 baseMinDamage = 50; int32 baseMaxDamage = 100; // NOTE: Some weapon data just for tesing and to give the npc a fair chance... if (weapon->hasAttribute("cat_wpn_damage.wpn_damage_min")) { baseMinDamage = weapon->getAttribute<int32>("cat_wpn_damage.wpn_damage_min"); } if (weapon->hasAttribute("cat_wpn_damage.wpn_damage_max")) { baseMaxDamage = weapon->getAttribute<int32>("cat_wpn_damage.wpn_damage_max"); } //Sanity checks of db data if (baseMinDamage < 1) baseMinDamage = 1; if (baseMaxDamage < 1) baseMaxDamage = 1; if(baseMaxDamage <= baseMinDamage) { baseMaxDamage = baseMinDamage +1; } int32 baseDamage = -((gRandom->getRand()%(baseMaxDamage - baseMinDamage)) + baseMinDamage); // apply damage multiplier if(cmdProperties->mDamageMultiplier) { multipliedDamage = static_cast<uint32>(static_cast<float>(baseDamage) * cmdProperties->mDamageMultiplier); } else { multipliedDamage = baseDamage; } // mitigation multipliedDamage = _mitigateDamage(attacker,defender,cmdProperties,multipliedDamage,weapon); // state effects stateApplied = _tryStateEffects(attacker,defender,cmdProperties,weapon); // Here is the deal. When a player makes damage to a npc, we have to register the player, its group, damage done and what (kind of) weapon used. NPCObject* npc = dynamic_cast<NPCObject*>(defender); if (!defender->isDead() && npc) { PlayerObject* player = dynamic_cast<PlayerObject*>(attacker); if (player) { npc->updateDamage(player->getId(), player->getGroupId(), weapon->getGroup(), -multipliedDamage, player->GetPosture(), glm::distance(defender->mPosition, player->mPosition)); } } // ham damage // if no target pool set, pick a random one if(!cmdProperties->mHealthHitChance && !cmdProperties->mActionHitChance && !cmdProperties->mMindHitChance) { switch(gRandom->getRand()%3) { case 0: randomHitPool = HamBar_Health; break; case 1: randomHitPool = HamBar_Action; break; case 2: randomHitPool = HamBar_Mind; break; default: randomHitPool = 0; break; } } auto ham = gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::ham::HamService>("HamService"); //this is pure idiocy in my eyes. Why for gods sake should an object be a creature ? // is there precedent through SOE??????????? if (defender->getCreoGroup() != CreoGroup_AttackableObject) { // random pool attack if(randomHitPool != 100) { ham->UpdateCurrentHitpoints(defender,randomHitPool,multipliedDamage); //defender->getHam()->updatePropertyValue(randomHitPool,HamProperty_CurrentHitpoints,multipliedDamage,true); } // direct pool attack else { // health hit if(cmdProperties->mHealthHitChance) { ham->UpdateCurrentHitpoints(defender,HamBar_Health,multipliedDamage); //defender->getHam()->updatePropertyValue(HamBar_Health,HamProperty_CurrentHitpoints,multipliedDamage,true); } // action hit else if(cmdProperties->mActionHitChance) { ham->UpdateCurrentHitpoints(defender,HamBar_Action,multipliedDamage); //defender->getHam()->updatePropertyValue(HamBar_Action,HamProperty_CurrentHitpoints,multipliedDamage,true); } // mind hit else if(cmdProperties->mMindHitChance) { ham->UpdateCurrentHitpoints(defender,HamBar_Mind,multipliedDamage); //defender->getHam()->updatePropertyValue(HamBar_Mind,HamProperty_CurrentHitpoints,multipliedDamage,true); } } } else { ham->UpdateCurrentHitpoints(defender,HamBar_Health,multipliedDamage); //defender->getHam()->updateSingleHam(multipliedDamage, true); } if (defender->isIncapacitated()) { PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker); if (playerAttacker && playerAttacker->isConnected()) { gMessageLib->SendSystemMessage(::common::OutOfBand("base_player", "prose_target_incap", 0, defender->getId(), 0), playerAttacker); } } if (defender->isDead()) { PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker); if (playerAttacker && playerAttacker->isConnected()) { gMessageLib->SendSystemMessage(::common::OutOfBand("base_player", "killer_target_dead"), playerAttacker, true); } } } // fly text and animations // default attack(s) if(cmdProperties->mCmdCrc == 0xa8fef90a) { uint32 animCrc = getDefaultAttackAnimation(weapon->getGroup()); switch(attackResult) { // hit case 0: case 2: case 3: case 4: { gMessageLib->sendCombatAction(attacker,defender,animCrc,0,0,1); } break; // miss case 1: { gMessageLib->sendCombatAction(attacker,defender,animCrc); } break; } } // special attack else { switch(attackResult) { // hit case 0: case 2: case 3: case 4: { gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2,1); } break; //miss case 1: { gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2); } break; } } switch(attackResult) { case 0: { // Defender got hit. } break; case 1: { gMessageLib->sendFlyText(defender,"combat_effects","miss",255,255,255); } break; case 2: // We cant block yet, can we? { gMessageLib->sendFlyText(defender,"combat_effects","block",0,255,0); gMessageLib->sendCombatAction(defender,attacker,0xe430ff04); } break; case 3: { gMessageLib->sendFlyText(defender,"combat_effects","dodge",0,255,0); gMessageLib->sendCombatAction(defender,attacker,0xe430ff04); // Dodge } break; case 4: { gMessageLib->sendFlyText(defender,"combat_effects","counterattack",0,255,0); // I can's see this effect working? } break; } // send combat spam // default attack if(cmdProperties->mCmdCrc == 0xa8fef90a) { combatSpam = getDefaultSpam(weapon->getGroup()); } // special attack else { if(cmdProperties->mCbtSpam.getLength()) { combatSpam = cmdProperties->mCbtSpam.getAnsi(); } } switch(attackResult) { case 0: combatSpam << "_hit"; break; case 1: combatSpam << "_miss"; break; case 2: combatSpam << "_block"; break; case 3: combatSpam << "_evade"; break; case 4: combatSpam << "_counter"; break; default: break; } gMessageLib->sendCombatSpam(attacker,defender,-multipliedDamage,"cbt_spam",combatSpam); return(0); }