- Strength damage now applicable to both low and high damage
* New rules: * R_Combat, StrengthNPC = 10 * R_Combat, StrengthOther = 25 * these are dividers, player_strength / 25 (or for NPCs a divide by 10), minimum value of 1 allowed - ChangeLevel now properly called inside AddXP when player level changes (this is required!) else skill ups do not occur. - Added weaponry to skillups (piercing, slashing, so on) since it wasn't skilling up - Fixed crash upon not being able to load a recipe (if someone were to remove recipes from the DB that a character needed)
This commit is contained in:
parent
27cc0415c0
commit
dc8b469de3
9 changed files with 80 additions and 71 deletions
EQ2/source/WorldServer
|
@ -714,6 +714,7 @@ void Entity::ChangePrimaryWeapon(){
|
|||
return;
|
||||
}
|
||||
|
||||
int32 str_offset_dmg = GetStrengthDamage();
|
||||
Item* item = equipment_list.GetItem(EQ2_PRIMARY_SLOT);
|
||||
if(item && item->details.item_id > 0 && item->IsWeapon()){
|
||||
GetInfoStruct()->set_primary_weapon_delay(item->weapon_info->delay * 100);
|
||||
|
@ -728,8 +729,8 @@ void Entity::ChangePrimaryWeapon(){
|
|||
effective_level = GetLevel();
|
||||
|
||||
GetInfoStruct()->set_primary_weapon_delay(2000);
|
||||
GetInfoStruct()->set_primary_weapon_damage_low((int32)1 + effective_level * .2);
|
||||
GetInfoStruct()->set_primary_weapon_damage_high((int32)(5 + effective_level * (effective_level/5)));
|
||||
GetInfoStruct()->set_primary_weapon_damage_low((int32)1 + (effective_level * .2) + str_offset_dmg);
|
||||
GetInfoStruct()->set_primary_weapon_damage_high((int32)(5 + effective_level * (effective_level/5)) + str_offset_dmg);
|
||||
if(GetInfoStruct()->get_attack_type() > 0) {
|
||||
GetInfoStruct()->set_primary_weapon_type(GetInfoStruct()->get_attack_type());
|
||||
}
|
||||
|
@ -738,14 +739,6 @@ void Entity::ChangePrimaryWeapon(){
|
|||
}
|
||||
GetInfoStruct()->set_wield_type(2);
|
||||
}
|
||||
|
||||
int32 weapon_dmg_high = GetInfoStruct()->get_primary_weapon_damage_high();
|
||||
if(IsNPC()) {
|
||||
GetInfoStruct()->set_primary_weapon_damage_high(weapon_dmg_high + (int32)((GetInfoStruct()->get_str() / 10)));
|
||||
}
|
||||
else {
|
||||
GetInfoStruct()->set_primary_weapon_damage_high(weapon_dmg_high + (int32)((GetInfoStruct()->get_str() / 25)));
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::ChangeSecondaryWeapon(){
|
||||
|
@ -753,11 +746,13 @@ void Entity::ChangeSecondaryWeapon(){
|
|||
return;
|
||||
}
|
||||
|
||||
int32 str_offset_dmg = GetStrengthDamage();
|
||||
|
||||
Item* item = equipment_list.GetItem(EQ2_SECONDARY_SLOT);
|
||||
if(item && item->details.item_id > 0 && item->IsWeapon()){
|
||||
GetInfoStruct()->set_secondary_weapon_delay(item->weapon_info->delay * 100);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_low(item->weapon_info->damage_low3);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high(item->weapon_info->damage_high3);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_low(item->weapon_info->damage_low3 + str_offset_dmg);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high(item->weapon_info->damage_high3 + str_offset_dmg);
|
||||
GetInfoStruct()->set_secondary_weapon_type(item->GetWeaponType());
|
||||
}
|
||||
else{
|
||||
|
@ -766,18 +761,10 @@ void Entity::ChangeSecondaryWeapon(){
|
|||
effective_level = GetLevel();
|
||||
|
||||
GetInfoStruct()->set_secondary_weapon_delay(2000);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_low((int32)(1 + effective_level * .2));
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high((int32)(5 + effective_level * (effective_level/6)));
|
||||
GetInfoStruct()->set_secondary_weapon_damage_low((int32)(1 + effective_level * .2) + str_offset_dmg);
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high((int32)(5 + effective_level * (effective_level/6)) + str_offset_dmg);
|
||||
GetInfoStruct()->set_secondary_weapon_type(1);
|
||||
}
|
||||
|
||||
int32 weapon_dmg_high = GetInfoStruct()->get_secondary_weapon_damage_high();
|
||||
if(IsNPC()) {
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high(weapon_dmg_high + (int32)((GetInfoStruct()->get_str() / 10)));
|
||||
}
|
||||
else {
|
||||
GetInfoStruct()->set_secondary_weapon_damage_high(weapon_dmg_high + (int32)((GetInfoStruct()->get_str() / 25)));
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::ChangeRangedWeapon(){
|
||||
|
@ -794,6 +781,23 @@ void Entity::ChangeRangedWeapon(){
|
|||
}
|
||||
}
|
||||
|
||||
int32 Entity::GetStrengthDamage() {
|
||||
int32 str_offset = 1;
|
||||
if(IsNPC()) {
|
||||
str_offset = rule_manager.GetGlobalRule(R_Combat, StrengthNPC)->GetInt32();
|
||||
if(str_offset < 1)
|
||||
str_offset = 1;
|
||||
}
|
||||
else {
|
||||
str_offset = rule_manager.GetGlobalRule(R_Combat, StrengthOther)->GetInt32();
|
||||
if(str_offset < 1)
|
||||
str_offset = 1;
|
||||
|
||||
}
|
||||
int32 str_offset_dmg = (int32)((GetInfoStruct()->get_str() / str_offset));
|
||||
return str_offset_dmg;
|
||||
}
|
||||
|
||||
int32 Entity::GetPrimaryWeaponMinDamage(){
|
||||
return GetInfoStruct()->get_primary_weapon_damage_low();
|
||||
}
|
||||
|
|
|
@ -1360,6 +1360,7 @@ public:
|
|||
void ChangePrimaryWeapon();
|
||||
void ChangeSecondaryWeapon();
|
||||
void ChangeRangedWeapon();
|
||||
int32 GetStrengthDamage();
|
||||
virtual Skill* GetSkillByName(const char* name, bool check_update = false);
|
||||
virtual Skill* GetSkillByID(int32 id, bool check_update = false);
|
||||
bool AttackAllowed(Entity* target, float distance = 0, bool range_attack = false);
|
||||
|
|
|
@ -10766,13 +10766,9 @@ int EQ2Emu_lua_GiveExp(lua_State* state) {
|
|||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
int32 amount = lua_interface->GetInt32Value(state, 2);
|
||||
|
||||
if (player && player->IsPlayer() && amount > 0) {
|
||||
((Player*)player)->AddXP(amount);
|
||||
((Player*)player)->SetCharSheetChanged(true);
|
||||
Client* client = player->GetZone()->GetClientBySpawn(player);
|
||||
if (client) {
|
||||
client->SimpleMessage(CHANNEL_REWARD, "You gain experience!");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1999,7 +1999,7 @@ vector<EQ2Packet*> Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
|
|||
packets.push_back(bag->serialize(version, false, this));
|
||||
}
|
||||
|
||||
if(send_item_updates)
|
||||
if(send_item_updates && GetClient())
|
||||
{
|
||||
GetClient()->UpdateSentSpellList();
|
||||
GetClient()->ClearSentSpellList();
|
||||
|
@ -2155,20 +2155,25 @@ vector<EQ2Packet*> Player::EquipItem(int16 index, int16 version, int8 appearance
|
|||
if(canEquip && !appearance_type && item->CheckFlag2(APPEARANCE_ONLY))
|
||||
{
|
||||
item_list.MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "This item is for appearance slots only.");
|
||||
if(GetClient()) {
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "This item is for appearance slots only.");
|
||||
}
|
||||
return packets;
|
||||
}
|
||||
else if(canEquip && (conflictSlot = equipList->CheckSlotConflict(item)) > 0) {
|
||||
bool abort = true;
|
||||
switch(conflictSlot) {
|
||||
case LORE:
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Lore conflict, cannot equip this item.");
|
||||
if(GetClient())
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Lore conflict, cannot equip this item.");
|
||||
break;
|
||||
case LORE_EQUIP:
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "You already have this item equipped, you cannot equip another.");
|
||||
if(GetClient())
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "You already have this item equipped, you cannot equip another.");
|
||||
break;
|
||||
case STACK_LORE:
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Cannot equip as it exceeds lore stack.");
|
||||
if(GetClient())
|
||||
GetClient()->SimpleMessage(CHANNEL_COLOR_RED, "Cannot equip as it exceeds lore stack.");
|
||||
break;
|
||||
default:
|
||||
abort = false;
|
||||
|
@ -3472,8 +3477,12 @@ void Player::AddSpellEffect(LuaSpell* luaspell, int32 override_expire_time){
|
|||
|
||||
if(luaspell->caster && luaspell->caster->IsPlayer() && luaspell->caster != this)
|
||||
{
|
||||
GetClient()->TriggerSpellSave();
|
||||
((Player*)luaspell->caster)->GetClient()->TriggerSpellSave();
|
||||
if(GetClient()) {
|
||||
GetClient()->TriggerSpellSave();
|
||||
}
|
||||
if(((Player*)luaspell->caster)->GetClient()) {
|
||||
((Player*)luaspell->caster)->GetClient()->TriggerSpellSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3916,7 +3925,7 @@ bool Player::SetSpawnSentState(Spawn* spawn, SpawnState state) {
|
|||
if(index > 0 && (state == SpawnState::SPAWN_STATE_SENDING)) {
|
||||
LogWrite(PLAYER__WARNING, 0, "Player", "Spawn ALREADY INDEXED for Player %s (%u). Spawn %s (index %u) attempted to state %u.",
|
||||
GetName(), GetCharacterID(), spawn->GetName(), index, state);
|
||||
if(GetClient()->IsReloadingZone()) {
|
||||
if(GetClient() && GetClient()->IsReloadingZone()) {
|
||||
spawn_packet_sent.insert(make_pair(spawn->GetID(), state));
|
||||
val = false;
|
||||
}
|
||||
|
@ -3958,7 +3967,7 @@ bool Player::SetSpawnSentState(Spawn* spawn, SpawnState state) {
|
|||
}
|
||||
|
||||
void Player::CheckSpawnStateQueue() {
|
||||
if(!GetClient()->IsReadyForUpdates())
|
||||
if(!GetClient() || !GetClient()->IsReadyForUpdates())
|
||||
return;
|
||||
|
||||
spawn_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
|
@ -4400,6 +4409,9 @@ int32 Player::GetTSXP() {
|
|||
}
|
||||
|
||||
bool Player::AddXP(int32 xp_amount){
|
||||
if(!GetClient()) // potential linkdead player
|
||||
return false;
|
||||
|
||||
MStats.lock();
|
||||
xp_amount += (int32)(((float)xp_amount) * stats[ITEM_STAT_COMBATEXPMOD]) / 100;
|
||||
MStats.unlock();
|
||||
|
@ -4430,14 +4442,18 @@ bool Player::AddXP(int32 xp_amount){
|
|||
}
|
||||
|
||||
// used up in xp debt
|
||||
if(!xp_amount)
|
||||
if(!xp_amount) {
|
||||
SetCharSheetChanged(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 prev_level = GetLevel();
|
||||
float current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
|
||||
float miniding_min_percent = ((int)(current_xp_percent/10)+1)*10;
|
||||
while((xp_amount + GetXP()) >= GetNeededXP()){
|
||||
if (!CheckLevelStatus(GetLevel() + 1)) {
|
||||
GetZone()->GetClientBySpawn(this)->SimpleMessage(CHANNEL_COLOR_RED, "You do not have the required status to level up anymore!");
|
||||
SetCharSheetChanged(true);
|
||||
return false;
|
||||
}
|
||||
xp_amount -= GetNeededXP() - GetXP();
|
||||
|
@ -4451,6 +4467,15 @@ bool Player::AddXP(int32 xp_amount){
|
|||
SetPower(GetTotalPower());
|
||||
GetZone()->SendCastSpellPacket(332, this, this); //send mini level up spell effect
|
||||
}
|
||||
|
||||
if(GetClient()) {
|
||||
GetClient()->Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp_amount);
|
||||
|
||||
if (prev_level != GetLevel())
|
||||
GetClient()->ChangeLevel(prev_level, GetLevel());
|
||||
}
|
||||
|
||||
SetCharSheetChanged(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,13 @@ void WorldDatabase::LoadPlayerRecipes(Player *player){
|
|||
res = query.RunQuery2(Q_SELECT, "SELECT recipe_id, highest_stage FROM character_recipes WHERE char_id = %u", player->GetCharacterID());
|
||||
if (res) {
|
||||
while ((row = mysql_fetch_row(res))){
|
||||
recipe = new Recipe(master_recipe_list.GetRecipe(atoul(row[0])));
|
||||
int32 recipe_id = atoul(row[0]);
|
||||
Recipe* master_recipe = master_recipe_list.GetRecipe(recipe_id);
|
||||
if(!master_recipe) {
|
||||
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error adding recipe %u to player '%s' - duplicate ID", atoul(row[0]), player->GetName());
|
||||
continue;
|
||||
}
|
||||
recipe = new Recipe(master_recipe);
|
||||
recipe->SetHighestStage(atoi(row[1]));
|
||||
|
||||
LogWrite(TRADESKILL__DEBUG, 5, "Recipes", "Loading recipe: %s (%u) for player: %s (%u)", recipe->GetName(), recipe->GetID(), player->GetName(), player->GetCharacterID());
|
||||
|
|
|
@ -244,6 +244,8 @@ void RuleManager::Init()
|
|||
RULE_INIT(R_Combat, MitigationLevelEffectivenessMin, ".5"); // ratio victim level / attacker level for min effectiveness
|
||||
RULE_INIT(R_Combat, MaxMitigationAllowed, ".75"); // percentage max mitigation allowed, eg. 75% of damage can be mitigated max in PVE
|
||||
RULE_INIT(R_Combat, MaxMitigationAllowedPVP, ".75"); // percentage max mitigation allowed, eg. 75% of damage can be mitigated max in PVP
|
||||
RULE_INIT(R_Combat, StrengthNPC, "10"); // divider for strength NPC only str/x = additional dmg to low/high dmg
|
||||
RULE_INIT(R_Combat, StrengthOther, "25"); // divider for strength other than NPC str/x = additional dmg to low/high dmg
|
||||
|
||||
/* SPAWN */
|
||||
RULE_INIT(R_Spawn, SpeedMultiplier, "300"); // note: this value was 1280 until 6/1/2009, then was 600 til Sep 2009, when it became 300...?
|
||||
|
|
|
@ -103,6 +103,8 @@ enum RuleType {
|
|||
MitigationLevelEffectivenessMin,
|
||||
MaxMitigationAllowed,
|
||||
MaxMitigationAllowedPVP,
|
||||
StrengthNPC,
|
||||
StrengthOther,
|
||||
|
||||
/* SPAWN */
|
||||
SpeedMultiplier,
|
||||
|
|
|
@ -840,6 +840,7 @@ void Client::SendCharInfo() {
|
|||
this->zoning_id = 0;
|
||||
this->zoning_instance_id = 0;
|
||||
SetZoningDestination(nullptr);
|
||||
|
||||
if (player->GetHP() < player->GetTotalHP() || player->GetPower() < player->GetTotalPower())
|
||||
GetCurrentZone()->AddDamagedSpawn(player);
|
||||
|
||||
|
@ -4621,6 +4622,7 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
player_skills->SetSkillCapsByType(SKILL_TYPE_GENERAL, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_SPELLCASTING, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_AVOIDANCE, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_WEAPONRY, new_skill_cap);
|
||||
|
||||
if (new_level > player->GetTSLevel())
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_HARVESTING, new_skill_cap);
|
||||
|
@ -6423,14 +6425,8 @@ void Client::GiveQuestReward(Quest* quest, bool has_displayed) {
|
|||
|
||||
if(!has_displayed) {
|
||||
if (quest->GetExpReward() > 0) {
|
||||
int16 level = player->GetLevel();
|
||||
int32 xp = quest->GetExpReward();
|
||||
if (player->AddXP(xp)) {
|
||||
Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp);
|
||||
if (player->GetLevel() != level)
|
||||
ChangeLevel(level, player->GetLevel());
|
||||
player->SetCharSheetChanged(true);
|
||||
}
|
||||
player->AddXP(xp);
|
||||
}
|
||||
if (quest->GetTSExpReward() > 0) {
|
||||
int8 ts_level = player->GetTSLevel();
|
||||
|
@ -9733,10 +9729,8 @@ void Client::AcceptCollectionRewards(Collection* collection, int32 selectable_it
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (collection->GetRewardXP() > 0) {
|
||||
player->AddXP((int32)collection->GetRewardXP());
|
||||
SimpleMessage(CHANNEL_COLOR_YELLOW, "You gain experience!");
|
||||
}
|
||||
if (collection->GetRewardCoin() > 0) {
|
||||
player->AddCoins(collection->GetRewardCoin());
|
||||
|
|
|
@ -4381,14 +4381,7 @@ void ZoneServer::SendCalculatedXP(Player* player, Spawn* victim){
|
|||
if(group_member) {
|
||||
float xp = group_member->CalculateXP(victim) / members->size();
|
||||
if (xp > 0) {
|
||||
int16 level = group_member->GetLevel();
|
||||
if (group_member->AddXP((int32)xp)) {
|
||||
gmi->client->Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp);
|
||||
LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience (GroupID %u)", group_member->GetName(), (int32)xp, player->GetGroupMemberInfo()->group_id);
|
||||
if (group_member->GetLevel() != level)
|
||||
gmi->client->ChangeLevel(level, group_member->GetLevel());
|
||||
group_member->SetCharSheetChanged(true);
|
||||
}
|
||||
group_member->AddXP((int32)xp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4404,14 +4397,7 @@ void ZoneServer::SendCalculatedXP(Player* player, Spawn* victim){
|
|||
Client* client = GetClientBySpawn(player);
|
||||
if(!client)
|
||||
return;
|
||||
int16 level = player->GetLevel();
|
||||
if (player->AddXP((int32)xp)) {
|
||||
client->Message(CHANNEL_REWARD, "You gain %u XP!", (int32)xp);
|
||||
LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", player->GetName(), (int32)xp);
|
||||
if(player->GetLevel() != level)
|
||||
client->ChangeLevel(level, player->GetLevel());
|
||||
player->SetCharSheetChanged(true);
|
||||
}
|
||||
player->AddXP((int32)xp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4660,14 +4646,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
|
|||
|
||||
float xp = ((Player*)spawn)->CalculateXP(dead) / size;
|
||||
if (xp > 0) {
|
||||
int16 level = spawn->GetLevel();
|
||||
if (((Player*)spawn)->AddXP((int32)xp)) {
|
||||
client->Message(CHANNEL_REWARD, "You gain %u XP!", (int32)xp);
|
||||
LogWrite(PLAYER__DEBUG, 0, "Player", "Player: %s earned %u experience.", spawn->GetName(), (int32)xp);
|
||||
if (spawn->GetLevel() != level)
|
||||
client->ChangeLevel(level, spawn->GetLevel());
|
||||
((Player*)spawn)->SetCharSheetChanged(true);
|
||||
}
|
||||
((Player*)spawn)->AddXP((int32)xp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue