void QuestManager::castspell(int spell_id, int target_id) { if (owner) { Mob *tgt = entity_list.GetMob(target_id); if(tgt != NULL) owner->SpellFinished(spells_handler.GetSpellPtr(spell_id), target_id); } }
void QuestManager::selfcast(int spell_id) { if (initiator) initiator->SpellFinished(spells_handler.GetSpellPtr(spell_id), initiator->GetID(),SLOT_ITEMSPELL); }
/////////////////////////////////////////////////// // Quagmire - that case above getting to long and spells are gonna have a lot of cases of their own // Cofruben - Reorganised this a little. void Mob::SpellEffect(Mob* caster, Spell* spell, int8 caster_level, bool partialResist) { //Spells not loaded! if(!spells_handler.SpellsLoaded()) return; //Spell not loaded! if(!spell) return; //Yeahlight: Caster was not supplied if(!caster) return; int i = 0; const int16 spell_id = spell->GetSpellID(); const char* teleport_zone = spell->GetSpellTeleportZone(); // 1. Is it a buff? If so, handle its time based effects. if (spell->IsBuffSpell()) spells_handler.HandleBuffSpellEffects(caster, this, spell); // 2. Handle its single-time effect. for (i = 0; i < EFFECT_COUNT; i++) { TSpellEffect effect_id = spell->GetSpellEffectID(i); if(effect_id == SE_Blank || effect_id == 0xFF) continue; int8 formula = spell->GetSpellFormula(i); sint16 base = spell->GetSpellBase(i); sint16 max = spell->GetSpellMax(i); sint32 amount = spells_handler.CalcSpellValue(spell, i, caster_level); //Yeahlight: This is an NPC and had a detremental spell casted upon it if(this->IsNPC() && (spell->IsDetrimentalSpell() || spell->IsUtilitySpell())) { CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): aggroing %s because of the spell effect!", spell->GetSpellName(), this->GetName()); //Yeahlight: Generate hate based on the spells's effect type sint16 tempHate = GetSpellHate(effect_id, spell->GetMinLevel(), false, amount); if(tempHate) { this->CastToNPC()->AddToHateList(caster, 0, tempHate); } } switch(effect_id) { case SE_CurrentHP: case SE_CurrentHPOnce: { sint32 OldHP = this->GetHP(); sint32 damage = amount; //Yeahlight: Partial resist calculations if(partialResist) { damage = damage / 2; damage = damage * (float)((float)(rand()%90 + 10) / 100.00f); if(caster->IsClient() && caster->CastToClient()->GetDebugMe()) caster->Message(YELLOW, "Debug: Your direct damage spell resist has been upgrade to a partial resist."); } this->ChangeHP(caster, damage, spell_id); sint32 NewHP = this->GetHP(); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You changed %s's hp by %+i.", spell->GetSpellName(), this->GetName(), damage); break; } case SE_MovementSpeed: { //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Movement Speed spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_AttackSpeed: { //Yeahlight: There should not be any work to be done here CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Attack Speed spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Invisibility: { this->SetInvisible(true); //Yeahlight: Castee has a pet; remove it if(GetPet()) { Mob* myPet = GetPet(); //Yeahlight: Castee's pet is an NPC if(myPet->IsNPC()) { //Yeahlight: Castee's pet is a charmed NPC if(myPet->CastToNPC()->IsCharmed()) { myPet->CastToNPC()->BuffFadeByEffect(SE_Charm); } //Yeahlight: Castee's pet is a summoned NPC else { myPet->Depop(); } } //Yeahlight: Castee's pet is a charmed PC else if(myPet->IsClient() && myPet->CastToClient()->IsCharmed()) { myPet->CastToClient()->BuffFadeByEffect(SE_Charm); } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an invisibility spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_CurrentMana: { SetMana(GetMana() + amount); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a mana recovery spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_AddFaction: { //Yeahlight: Only continue if the target is an NPC and the caster is a PC if(this->IsNPC() && caster->IsClient()) { caster->CastToClient()->SetCharacterFactionLevelModifier(this->CastToNPC()->GetPrimaryFactionID(), amount); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an add faction spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Stun: { if (IsClient()) { CastToClient()->Stun(base); } else if(IsNPC()) { //Yeahlight: NPC is immune to stun effects if(CastToNPC()->GetCannotBeStunned()) { if(caster->IsClient()) { caster->Message(RED, "Your target is immune to the stun portion of this effect"); } } else { CastToNPC()->Stun(base); } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a stun spell, amount: %i.", spell->GetSpellName(), base); break; } case SE_Charm: { //Yeahlight: Can only charm a non-pet and the caster may only have one pet if(this->GetOwner() == NULL && caster->GetPet() == NULL && caster != this) { //Yeahlight: Flag the NPC as a pet if(this->IsNPC()) { caster->SetPet(this); this->SetOwnerID(caster->GetID()); this->CastToNPC()->SetCharmed(true); this->SetPetOrder(SPO_Follow); if(caster->IsClient()) caster->CastToClient()->SendCharmPermissions(); this->CastToNPC()->WhipeHateList(); this->CastToNPC()->StartTaunting(); } else if(this->IsClient()) { if(caster->IsNPC()) { caster->SetPet(this); this->SetOwnerID(caster->GetID()); Mob* myTarget = caster->CastToNPC()->GetHateTop(); if(!myTarget) myTarget = caster->CastToMob(); this->SetTarget(myTarget); this->animation = 0; this->delta_heading = 0; this->delta_x = 0; this->delta_y = 0; this->delta_z = 0; this->SendPosUpdate(true, PC_UPDATE_RANGE, false); this->CastToClient()->charmPositionUpdate_timer->Start(200); this->CastToClient()->SetCharmed(true); this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false); this->SetPetOrder(SPO_Follow); } else if(caster->IsClient()) { caster->SetPet(this); this->SetOwnerID(caster->GetID()); this->SetTarget(caster); this->animation = 0; this->delta_heading = 0; this->delta_x = 0; this->delta_y = 0; this->delta_z = 0; this->SendPosUpdate(true, PC_UPDATE_RANGE, false); this->CastToClient()->charmPositionUpdate_timer->Start(200); this->CastToClient()->SetCharmed(true); this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false); this->SetPetOrder(SPO_Follow); caster->CastToClient()->SendCharmPermissions(); } } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a charm spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Fear: { //Yeahlight: Victim is a PC if(this->IsClient()) { this->CastToClient()->SetFeared(true); this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false); this->CastToClient()->GetFearDestination(GetX(), GetY(), GetZ()); } //Yeahlight: Victim is an NPC else if(this->IsNPC()) { this->CastToNPC()->SetFeared(true); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a fear spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Stamina: { CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a stamina spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_BindAffinity: { //Yeahlight: Target of the bind affinity spell is a client if(this->IsClient()) { this->CastToClient()->SetBindPoint(); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Bind Affinity spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Gate: { if(IsClient()) CastToClient()->GoToBind(); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a gate spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_CancelMagic: { for(int i = 0; i < 15; i++) { //Yeahlight: Buff must exist and the buff may not have any poison or disease counters if(buffs[i].spell && buffs[i].spell->IsValidSpell() && buffs[i].casterlevel <= (caster_level + base) && buffs[i].spell->GetDiseaseCounters() == 0 && buffs[i].spell->GetPoisonCounters() == 0) { this->BuffFadeBySlot(i, true); break; } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a cancel magic spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_InvisVsUndead: { this->SetInvisibleUndead(true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an Invis VS Undead spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_InvisVsAnimals: { this->SetInvisibleAnimal(true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an Invis VS Animal spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Mez: { // Pinedepain // When a mezz spell is casted, we mesmerize this mob Mesmerize(); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a mesmerize spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_SummonItem: { if(this->IsClient()) { if(amount == 0) this->CastToClient()->SummonItem(base, 1); else this->CastToClient()->SummonItem(base, (amount > 20) ? 20 : amount); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a summon item spell: %i.", spell->GetSpellName(), base); break; } case SE_NecPet: case SE_SummonPet: { if (this->GetPetID() != 0) { Message(RED, "You\'ve already got a pet."); break; } this->MakePet(teleport_zone); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Summon pet / nec pet spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_DivineAura: { this->SetInvulnerable(true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Divine Aura, amount: %i.", spell->GetSpellName(), amount); break; } case SE_ShadowStep: { //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Shadow Step spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Rune: { //Yeahlight: Flag entity with rune for damage calculations hasRuneOn = true; CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Rune spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Levitate: { this->SendAppearancePacket(0, SAT_Levitate, 2, true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a levitate spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_SummonCorpse: { bool permit = false; Mob* corpseOwner = target; //Yeahlight: The target of this spell is not a PC or the caster is targeting themself if(!target || (target && !target->IsClient()) || target == this) { corpseOwner = this; permit = true; } //Yeahlight: Can only summon a PC's corpse if(corpseOwner && corpseOwner->IsClient()) { //Yeahlight: PCs must be grouped to summon a corpse if(!permit) { Group* targetGroup = entity_list.GetGroupByClient(corpseOwner->CastToClient()); Group* myGroup = NULL; if(this->IsClient()) myGroup = entity_list.GetGroupByClient(this->CastToClient()); //Yeahlight: Caster is in a group and they share the same group as the target if(myGroup != NULL && myGroup == targetGroup) permit = true; } //Yeahlight: Caster may proceed with the summon if(permit) { Corpse *corpse = entity_list.GetCorpseByOwner(corpseOwner->CastToClient()); //Yeahlight: Corpse has been located if(corpse) { corpse->Summon(corpseOwner->CastToClient(), caster->CastToClient(), true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a summon corpse spell: %s.", spell->GetSpellName(), this->GetName()); } //Yeahlight: There is no corpse available else { //Yeahlight: Caster failed to locate his/her corpse if(caster == corpseOwner) { caster->Message(RED, "You do not have a corpse in this zone."); } //Yeahlight: Caster failed to locate their target's corpse else { caster->Message(RED, "Your target does not have a corpse in this zone."); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): Summon corpse: you can't sense the corpse: %i.", spell->GetSpellName()); } } else { //Yeahlight: TODO: This is not the correct message Message(RED, "You and your target must be in the same group to perform this action."); } } break; } case SE_Illusion: { SendIllusionPacket(base, GetDefaultGender(base, GetBaseGender()), GetTexture(), GetHelmTexture()); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an illusion spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Identify: { //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an identify spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_WipeHateList: { //Yeahlight: NOTE: Do NOT wipe the rampage list here; that never goes away until the mob resets if(this->IsNPC()) { //Yeahlight: TODO: I don't remember this message, look into this entity_list.MessageClose(this, true, DEFAULT_MESSAGE_RANGE, DARK_BLUE, "My mind fogs. Who are my friends? Who are my enemies?... it was all so clear a moment ago..."); this->CastToNPC()->WhipeHateList(); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a whipe hate list spell, amount: %i.", spell->GetSpellName(), amount); } break; } case SE_SpinTarget: { Spin(caster, spell); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a spin target spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_EyeOfZomm: { //Yeahlignt: Only produce eyes of zomm for PCs if(this->IsClient()) { if(this->CastToClient()->myEyeOfZomm == 0) MakeEyeOfZomm(this); else Message(RED, "You may only have one eye of zomm out at a time!"); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Eye Of Zomm spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_ReclaimPet: { //Yeahlight: Target of the spell is an uncharmed NPC, has an owner and the owner is the caster of the spell if(IsNPC() && CastToNPC()->IsCharmed() == false && GetOwnerID() && caster->GetID() == GetOwnerID()) { //Yeahlight: TODO: Research this formula caster->SetMana(caster->GetMana()+(GetLevel()*4)); if(caster->IsClient()) { caster->CastToClient()->SetPet(0); } SetOwnerID(0); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a reclaim pet spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_FeignDeath: { if(this->IsClient()) this->CastToClient()->FeignDeath(this->CastToClient()->GetSkill(ABJURATION)); break; } case SE_VoiceGraft: { //Yeahlight: Only allow voice graft to be casted on NPCs (we don't want PCs griefing other charmed PCs with /say) if(IsNPC() && caster->IsClient() && CastToNPC()->GetOwner() == caster) { caster->CastToClient()->SetVoiceGrafting(true); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a voice graft spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Revive: { //Yeahlight: Handled in client_process.cpp CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a revive spell, amount: %i, corpse: %s.", spell->GetSpellName(), amount, this->GetName()); break; } case SE_Teleport: { char teleport_zone_char[64]; if(this->IsClient()) strcpy(teleport_zone_char, teleport_zone); this->CastToClient()->MovePC(teleport_zone_char, spell->GetSpellBase(1), spell->GetSpellBase(0), spell->GetSpellBase(2), false, false); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a teleport spell to %s (%f, %f, %f).", spell->GetSpellName(), teleport_zone, spell->GetSpellBase(1), spell->GetSpellBase(0), spell->GetSpellBase(2)); break; } case SE_Translocate: { bool permit = false; Mob* translocatee = CastToMob(); //Enraged: The target of this spell is an NPC. //if(translocatee && !translocatee->IsClient()) //{ // //Enraged: TODO: This is not the correct message? // Message(RED, "You cannot cast that spell on your current target."); // break; //} //Enraged: The target of this spell is the caster. //TODO: Can players target themselves with translocate spells? if(translocatee && (translocatee == this)) permit = true; //Enraged: Check if the targetted client is in the casters group. //TODO: Translocate only worked on group players, right? if(!permit && translocatee) { Group* translocateeGroup = entity_list.GetGroupByClient(translocatee->CastToClient()); Group* casterGroup = NULL; if(this->IsClient()) casterGroup = entity_list.GetGroupByClient(this->CastToClient()); //Enraged: The translocatee is in a group and they share the same group as the target if(casterGroup != NULL && casterGroup == translocateeGroup) permit = true; } //Enraged: Target is clear to be translocated. if(permit) { CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a translocation spell on %s.", spell->GetSpellName(), translocatee->GetName()); //TODO: Translocate code here translocatee->CastToClient()->SendTranslocateConfirmation(caster, spell); } else { //The translocatee was not in the casters group. //Enraged: TODO: This is not the correct message Message(RED, "You can only cast that spell on players in your group."); } break; } case SE_InfraVision: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an infravision spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_UltraVision: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an ultravision spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_BindSight: CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a bind sight spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_SeeInvis: SetCanSeeThroughInvis(true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a see invis spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_WaterBreathing: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an water breathing spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_SenseDead: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense dead spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_SenseSummoned: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense summoned spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_TrueNorth: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a true north spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_SenseAnimals: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense animals spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_DamageShield: //Yeahlight: There should not be any work to be done here CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a damage shield spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_Sentinel: CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sentinel spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_LocateCorpse: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a locate corpse spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_ModelSize: { //Yeahlight: Grow/Shrink float newSize = (GetSize() * (float)base) / 100.00f; //Yeahlight: Size of a gnome (minimum) if(newSize < 3) newSize = 3; //Yeahlight: Size of an ogre (maximum) else if(newSize > 9) newSize = 9; this->size = newSize; this->SendAppearancePacket(GetID(), SAT_Size, GetSize(), true); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a model size spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Root: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a root spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_Blind: //Yeahlight: Handled client side CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a blind spell, amount: %i.", spell->GetSpellName(), amount); break; case SE_DiseaseCounter: { //Yeahlight: Spell is a cure disease spell if(amount < 0) { //Yeahlight: Iterate through all the debuffs on the target and check for the chance to cure it for(int i = 0; i < 15; i++) { if(buffs[i].spell && buffs[i].diseasecounters) { buffs[i].diseasecounters = buffs[i].diseasecounters + amount; if(buffs[i].diseasecounters <= 0) BuffFadeBySlot(i, true); break; } } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a disease counter spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_PoisonCounter: { //Yeahlight: Spell is a cure poison spell if(amount < 0) { //Yeahlight: Iterate through all the debuffs on the target and check for the chance to cure it for(int i = 0; i < 15; i++) { if(buffs[i].spell && buffs[i].poisoncounters) { buffs[i].poisoncounters = buffs[i].poisoncounters + amount; if(buffs[i].poisoncounters <= 0) BuffFadeBySlot(i, true); break; } } } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a poison counter spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_Calm: { //Yeahlight: Only add/remove hate from NPCs if(this->IsNPC()) { this->CastToNPC()->AddToHateList(caster, 0, amount); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a calm hate spell, amount: %i.", spell->GetSpellName(), amount); break; } case SE_WeaponProc: { Spell* spell = spells_handler.GetSpellPtr(base); //Yeahlight: Legit spell proc bonus found if(spell) SetBonusProcSpell(spell); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell name = %s): Weapon proc bonus of spell ID %i.", spell->GetSpellName(), base); break; } case SE_StopRain: { zone->zone_weather = 0; zone->weatherSend(); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a stop rain spell, amount: %i.", spell->GetSpellName(), base); break; } case SE_CallOfHero: { //Yeahlight: Call of the Hero may only be used on PCs int32 zoneid = 0; if(this->IsClient()) this->CastToClient()->MovePC(zoneid, caster->GetX(), caster->GetY(), caster->GetZ(), false, true); else caster->Message(RED, "This spell may only be cast on players."); CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a call of the hero spell, amount: %i.", spell->GetSpellName(), base); break; } case SE_CallPet: { //Yeahlight: This spell line may only be used on NPC pets if(GetPet() && GetPet()->IsNPC()) { GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading()); GetPet()->pStandingPetOrder = SPO_Follow; } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a call pet spell, amount: %i.", spell->GetSpellName(), base); break; } case SE_DeathSave: { //Yeahlight: Only apply divine intervention to players if(this->IsClient()) { sint16 successChance = 0; float baseChance = 0.00f; switch(base) { //Yeahlight: Death Pact (CLR: 51) case 1: { baseChance = 0.10f; break; } //Yeahlight: Divine Intervention (CLR: 60) case 2: { baseChance = 0.30f; break; } default: { baseChance = 0.10f; } } //Yeahlight: The target's CHA is calculated into the bonus save chance successChance = (((float)CastToClient()->GetCHA() * 0.0005f) + baseChance) * 100; //Yeahlight: The worst possible save chance is the spell's base chance if(successChance < baseChance) successChance = baseChance; else if(successChance > 100) successChance = 100; this->CastToClient()->SetDeathSave(successChance); } CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a death save spell, amount: %i.", spell->GetSpellName(), base); break; } case SE_Succor: { //Yeahlight: There should be nothing to do here CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a succor spell, amount: %i.", spell->GetSpellName(), base); break; } case 0xFE: case 0xFF: case SE_Harmony: case SE_ChangeFrenzyRad: case SE_Lull: case SE_TotalHP: case SE_ArmorClass: case SE_MagnifyVision: case SE_ATK: case SE_STR: case SE_DEX: case SE_AGI: case SE_STA: case SE_INT: case SE_WIS: case SE_CHA: case SE_ResistFire: case SE_ResistCold: case SE_ResistPoison: case SE_ResistDisease: case SE_ResistMagic: { // Buffs are handeled elsewhere break; } default: { CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): unknown effect (%i) for amount: %i.", spell->GetSpellName(), effect_id, amount); break; } } } if(this->IsClient()) this->CastToClient()->Save(); }
int main(int argc, char** argv) { #ifdef WIN32 #ifdef WIN32_WORLD_SERVERONLY if(!EQC::Common::IsRunningOnWindowsServer()) { cout << "EQC Zone Server requires to be running on a Server Platform." << endl; exit(0); } #endif #endif #ifdef _DEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif if (argc != 5) { cerr << "Usage: zone zone_name address port worldaddress" << endl; exit(0); } char* zone_name = argv[1]; char* address = argv[2]; int32 port = atoi(argv[3]); char* worldaddress = argv[4]; if (strlen(address) <= 0) { cerr << "Invalid address" << endl; exit(0); } if (port <= 0) { cerr << "Bad port specified" << endl; exit(0); } if (strlen(worldaddress) <= 0) { cerr << "Invalid worldaddress" << endl; exit(0); } if (signal(SIGINT, CatchSignal) == SIG_ERR) { cerr << "Could not set signal handler" << endl; return 0; } net.SaveInfo(address, port, worldaddress); #ifdef EQC_SHAREDMEMORY // -Cofruben: Load Shared Memory EQC::Common::PrintF(CP_SHAREDMEMORY, "Loading Shared Memory Core..."); SharedMemory::Load(); EQC::Common::PrintF(CP_GENERIC, "Done.\n"); #else EQC::Common::PrintF(CP_ZONESERVER, "Loading items...\n"); Database::Instance()->LoadItems(); #endif EQC::Common::PrintF(CP_SPELL, "Loading SP DAT...\n"); spells_handler.LoadSpells(SPDat_Location); EQC::Common::PrintF(CP_ZONESERVER, "Loading guild and guild ranks...\n"); zgm.LoadGuilds(); EQC::Common::PrintF(CP_ZONESERVER, "Loading faction data...\n"); Database::Instance()->LoadFactionData(); EQC::Common::PrintF(CP_ZONESERVER, "Loading faction lists...\n"); Database::Instance()->LoadNPCFactionLists(); EQC::Common::PrintF(CP_ZONESERVER, "Loading Corpse decay Timers...\n"); Database::Instance()->GetDecayTimes(npcCorpseDecayTimes); if (!worldserver.Init()) { cerr << "InitWorldServer failed" << endl; } //Yeahlight: Static zone support if(strcmp(zone_name, ".") == 0) { EQC::Common::PrintF(CP_ZONESERVER, "Entering sleep mode.\n"); } else if(!Zone::Bootup(zone_name)) { EQC::Common::PrintF(CP_ZONESERVER, "%s boot FAILED!\n", zone_name); } else { EQC::Common::PrintF(CP_ZONESERVER, "%s boot was successful.\n", zone_name); } Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect net.StartProcessLoop(); MNetLoop.lock(); while(RunLoops) { Timer::SetCurrentTime(); if (ZoneLoaded) { net.ListenNewClients(); client_list.SendPacketQueues(); } if (InterserverTimer.Check()) { InterserverTimer.Start(); Database::Instance()->PingMySQL(); entity_list.UpdateWho(); } MNetLoop.unlock(); Sleep(1); MNetLoop.lock(); } MNetLoop.unlock(); if (zone != 0) Zone::Shutdown(true); while (WorldLoopRunning || ProcessLoopRunning) { Sleep(1); } #ifdef EQC_SHAREDMEMORY // -Cofruben: Unload Shared Memory. SharedMemory::Unload(); #endif return 0; }
void WorldServer::Process() { if(this == 0) { return; } if(!Connected()) { return; } SOCKADDR_IN to; memset((char *) &to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_port = port; to.sin_addr.s_addr = ip; /************ Get all packets from packet manager out queue and process them ************/ ServerPacket *pack = 0; while(pack = ServerRecvQueuePop()) { switch(pack->opcode) { case 0: { break; } case ServerOP_KeepAlive: { // ignore this break; } case ServerOP_ChannelMessage: { if (!ZoneLoaded) break; ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer; if (scm->deliverto[0] == 0) { entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message); } else { Client* client; client = entity_list.GetClientByName(scm->deliverto); if (client != 0) { if (client->Connected()) { client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message); if (!scm->noreply) { // if it's a tell, echo back so it shows up scm->noreply = true; scm->chan_num = 14; memset(scm->deliverto, 0, sizeof(scm->deliverto)); strcpy(scm->deliverto, scm->from); SendPacket(pack); } } } } break; } case ServerOP_EmoteMessage: { if (!ZoneLoaded) { break; } ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer; if (sem->to[0] != 0) { if (strcasecmp(sem->to, zone->GetShortName()) == 0) { entity_list.Message(sem->guilddbid, (MessageFormat)sem->type, sem->message); } else { Client* client = entity_list.GetClientByName(sem->to); if (client != 0) { client->Message((MessageFormat)sem->type, sem->message); } } } else { entity_list.Message(sem->guilddbid, (MessageFormat)sem->type, sem->message); } break; } /* case ServerOP_GroupRefresh: //Kibanu - 4/22/2009 { cout << "WorldServer_Process: In Group Refresh" << endl; if (!ZoneLoaded) { break; } ServerGroupRefresh_Struct* gr = (ServerGroupRefresh_Struct*) pack->pBuffer; if (gr->member[0] != 0) { cout << "WorldServer_Process: Refreshing group for " << gr->member << endl; Client* client = entity_list.GetClientByName(gr->member); if (client != 0) { client->RefreshGroup(gr->gid, gr->action); } } break; }*/ case ServerOP_ShutdownAll: { entity_list.Save(); CatchSignal(2); break; } case ServerOP_ZoneShutdown: { // Annouce the change to the world if (!ZoneLoaded) { SetZone(""); } else { worldserver.SendEmoteMessage(0, 0, 15, "Zone shutdown: %s", zone->GetLongName()); ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer; cout << "Zone shutdown by " << zst->adminname << endl; Zone::Shutdown(); } break; } case ServerOP_ZoneBootup: { ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer; if (ZoneLoaded) { SetZone(zone->GetShortName()); if (strcasecmp(Database::Instance()->GetZoneName(zst->zoneid), zone->GetShortName()) == 0) { // This packet also doubles as "incomming client" notification, lets not shut down before they get here zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { worldserver.SendEmoteMessage(zst->adminname, 0, 0, "Zone bootup failed: Already running '%s'", zone->GetShortName()); } break; } if (zst->adminname[0] != 0) { cout << "Zone bootup by " << zst->adminname << endl; } if (!(Zone::Bootup(Database::Instance()->GetZoneName(zst->zoneid)))) { worldserver.SendChannelMessage(0, 0, 10, 0, 0, "%s:%i Zone::Bootup failed: %s", net.GetZoneAddress(), net.GetZonePort(), Database::Instance()->GetZoneName(zst->zoneid)); } break; } case ServerOP_ZonePlayer: { ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(szp->name); if (client != 0) { if (strcasecmp(szp->adminname, szp->name) == 0) { client->Message(BLACK, "Zoning to: %s", szp->zone); } else if (client->GetAnon() == 1 && client->Admin() > szp->adminrank) { break; } else { worldserver.SendEmoteMessage(szp->adminname, 0, 0, "Summoning %s to %s %1.1f, %1.1f, %1.1f", szp->name, szp->zone, szp->x_pos, szp->y_pos, szp->z_pos); } client->SetIsZoning(true); client->SetUsingSoftCodedZoneLine(true); client->SetZoningHeading(client->GetHeading()); client->SetZoningX(szp->x_pos); client->SetZoningY(szp->y_pos); client->SetZoningZ(szp->z_pos); client->ZonePC(szp->zone, szp->x_pos, szp->y_pos, szp->z_pos); } break; } // Cofruben: used to send a packet directly to a client. /* case ServerOP_SendPacket: { ServerSendPacket_Struct* sss = (ServerSendPacket_Struct*)pack->pBuffer; int32 PacketSize = pack->size - sizeof(sss->charname) - sizeof(sss->opcode); Client* PacketTo = entity_list.GetClientByName(sss->charname); if(!PacketTo) { break; } APPLAYER* outapp = new APPLAYER(sss->opcode, PacketSize); memcpy(outapp->pBuffer, sss->packet, PacketSize); PacketTo->QueuePacket(outapp); safe_delete(outapp);//delete outapp; break; }*/ case ServerOP_KickPlayer: { ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(skp->name); if (client != 0) { if (skp->adminrank >= client->Admin()) { client->Kick(); if (ZoneLoaded) { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted in zone %s.", skp->name, zone->GetShortName()); } else { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted.", skp->name); } } else if (client->GetAnon() != 1) { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: Your avatar level is not high enough to kick %s", skp->name); } } break; } case ServerOP_KillPlayer: { ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(skp->target); if (client != 0) { if (skp->admin >= client->Admin()) { client->Kill(); if (ZoneLoaded) { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed in zone %s.", skp->target, zone->GetShortName()); } else { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed.", skp->target); } } else if (client->GetAnon() != 1) { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: Your avatar level is not high enough to kill %s", skp->target); } } break; } case ServerOP_RefreshGuild: { if (pack->size == 5) { int32 guildeqid = 0; memcpy(&guildeqid, pack->pBuffer, 4); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (pack->pBuffer[4] == 1) { APPLAYER* outapp = new APPLAYER(OP_GuildUpdate, 64); memset(outapp->pBuffer, 0, outapp->size); GuildUpdate_Struct* gu = (GuildUpdate_Struct*) outapp->pBuffer; gu->guildID = guildeqid; gu->entry.guildID = guildeqid; if (guilds[guildeqid].databaseID == 0) { gu->entry.exists = 0; // = 0x01 if exists, 0x00 on empty } else { strcpy(gu->entry.name, guilds[guildeqid].name); gu->entry.exists = 1; // = 0x01 if exists, 0x00 on empty } gu->entry.unknown1[0] = 0xFF; gu->entry.unknown1[1] = 0xFF; gu->entry.unknown1[2] = 0xFF; gu->entry.unknown1[3] = 0xFF; gu->entry.unknown3[0] = 0xFF; gu->entry.unknown3[1] = 0xFF; gu->entry.unknown3[2] = 0xFF; gu->entry.unknown3[3] = 0xFF; entity_list.QueueClients(0, outapp, false); safe_delete(outapp);//delete outapp; } } else cout << "Wrong size: ServerOP_RefreshGuild. size=" << pack->size << endl; break; } case ServerOP_GuildLeader: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if ((client->GuildRank() != 0) || (client->GuildRank() != 1)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not rank 0.", client->GetName()); } else { if (Database::Instance()->SetGuildLeader(sgc->guilddbid, client->AccountID())) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s is now the leader of your guild.", client->GetName()); ServerPacket* pack2 = new ServerPacket(ServerOP_RefreshGuild, 4); pack2->pBuffer = new uchar[pack->size]; memcpy(pack2->pBuffer, &sgc->guildeqid, 4); worldserver.SendPacket(pack2); safe_delete(pack2);//delete pack2; } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild leadership transfer failed."); } } break; } case ServerOP_GuildInvite: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (!guilds[sgc->guildeqid].rank[sgc->fromrank].invite) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to invite."); } else if (client->GuildDBID() != 0) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already in another guild.", client->GetName()); } else if (client->PendingGuildInvite != 0 && !(client->PendingGuildInvite == sgc->guilddbid)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s has another pending guild invite.", client->GetName()); } else { client->PendingGuildInvite = sgc->guilddbid; APPLAYER* outapp = new APPLAYER(OP_GuildInvite, sizeof(GuildCommand_Struct)); memset(outapp->pBuffer, 0, outapp->size); GuildCommand_Struct* gc = (GuildCommand_Struct*) outapp->pBuffer; gc->guildeqid = sgc->guildeqid; strcpy(gc->Inviter, sgc->target); strcpy(gc->Invitee, sgc->from); client->QueuePacket(outapp); /* if (client->SetGuild(sgc->guilddbid, GUILD_MAX_RANK)) worldserver.SendEmoteMessage(0, sgc->guilddbid, MT_Guild, "%s has joined the guild. Rank: %s.", client->GetName(), guilds[sgc->guildeqid].rank[GUILD_MAX_RANK].rankname); else worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild invite failed."); */ } break; } case ServerOP_GuildRemove: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if ((!guilds[sgc->guildeqid].rank[sgc->fromrank].remove) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to remove."); } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if (client->GuildRank() <= sgc->fromrank && !(sgc->fromaccountid == guilds[sgc->guildeqid].leader) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s's rank is too high for you to remove them.", client->GetName()); } else { if (client->SetGuild(0, GUILD_MAX_RANK)) { if (strcasecmp(sgc->from, sgc->target) == 0) { worldserver.SendEmoteMessage(0, sgc->guilddbid, GUILD, "%s has left the guild.", client->GetName()); } else { worldserver.SendEmoteMessage(0, sgc->guilddbid, GUILD, "%s has been removed from the guild by %s.", client->GetName(), sgc->from); client->Message(GUILD, "You have been removed from the guild by %s.", sgc->from); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild remove failed."); } } break; } case ServerOP_GuildPromote: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if ((!guilds[sgc->guildeqid].rank[sgc->fromrank].promote) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to promote."); } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s isnt in your guild.", client->GetName()); } else if (client->GuildRank() <= sgc->newrank) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already rank %i.", client->GetName(), client->GuildRank()); } else if (sgc->newrank <= sgc->fromrank && sgc->fromaccountid != guilds[sgc->guildeqid].leader) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You cannot promote people to a greater or equal rank than yourself."); } else { if (client->SetGuild(sgc->guilddbid, sgc->newrank)) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s has been promoted to %s by %s.", client->GetName(), guilds[sgc->guildeqid].rank[sgc->newrank].rankname, sgc->from); } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild promote failed"); } } break; } case ServerOP_GuildDemote: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if (!guilds[sgc->guildeqid].rank[sgc->fromrank].demote) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to demote."); } else if (client->GuildRank() >= sgc->newrank) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already rank %i.", client->GetName(), client->GuildRank()); } else if (sgc->newrank <= sgc->fromrank && sgc->fromaccountid != guilds[sgc->guildeqid].leader && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You cannot demote people with a greater or equal rank than yourself."); } else { if (client->SetGuild(sgc->guilddbid, sgc->newrank)) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s has been demoted to %s by %s.", client->GetName(), guilds[sgc->guildeqid].rank[sgc->newrank].rankname, sgc->from); } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild demote failed"); } } break; } case ServerOP_GuildGMSet: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client != 0) { if (client->GuildDBID() == 0 || sgc->guilddbid == 0) { if (!client->SetGuild(sgc->guilddbid, GUILD_MAX_RANK)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: Guild #%i not found", sgc->guilddbid); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: %s is already in a guild", sgc->target); } } break; } case ServerOP_GuildGMSetRank: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client != 0) { if (client->GuildDBID() != 0) { if (!client->SetGuild(client->GuildDBID(), sgc->newrank)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: SetRank failed.", sgc->guilddbid); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: %s is not in a guild", sgc->target); } } break; } /* case ServerOP_GuildCreateResponse: { GuildCreateResponse_Struct* gcrs = (GuildCreateResponse_Struct*) pack->pBuffer; if(gcrs->Created) { cout << "Guild " << gcrs->GuildName << " created." << endl; Client* client = entity_list.GetClientByName(gcrs->LeaderCharName); // invite the client to guild zgm.InviteToGuild(0, gcrs->eqid, client, client, GuildLeader); } break; }*/ case ServerOP_FlagUpdate: { Client* client = entity_list.GetClientByAccID(Database::Instance()->GetAccountIDByName((char*) pack->pBuffer)); if (client != 0) { client->UpdateAdmin(); } break; } case ServerOP_GMGoto: { if (pack->size != sizeof(ServerGMGoto_Struct)) { cout << "Wrong size on ServerOP_GMGoto. Got: " << pack->size << ", Expected: " << sizeof(ServerGMGoto_Struct) << endl; break; } if (!ZoneLoaded) { break; } ServerGMGoto_Struct* gmg = (ServerGMGoto_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(gmg->gotoname); if (client != 0) { worldserver.SendEmoteMessage(gmg->myname, 0, 13, "Summoning you to: %s @ %s, %1.1f, %1.1f, %1.1f", client->GetName(), zone->GetShortName(), client->GetX(), client->GetY(), client->GetZ()); ServerPacket* outpack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); outpack->pBuffer = new uchar[outpack->size]; memset(outpack->pBuffer, 0, outpack->size); ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) outpack->pBuffer; strcpy(szp->adminname, gmg->myname); strcpy(szp->name, gmg->myname); strcpy(szp->zone, zone->GetShortName()); szp->x_pos = client->GetX(); szp->y_pos = client->GetY(); szp->z_pos = client->GetZ(); worldserver.SendPacket(outpack); safe_delete(outpack);//delete outpack; } else { worldserver.SendEmoteMessage(gmg->myname, 0, 13, "Error: %s not found", gmg->gotoname); } break; } case ServerOP_MultiLineMsg: { ServerMultiLineMsg_Struct* mlm = (ServerMultiLineMsg_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(mlm->to); if (client) { APPLAYER* outapp = new APPLAYER(OP_MultiLineMsg, strlen(mlm->message)); strcpy((char*) outapp->pBuffer, mlm->message); client->QueuePacket(outapp); safe_delete(outapp);//delete outapp; } break; } case ServerOP_RezzPlayer: { RezzPlayer_Struct* srs = (RezzPlayer_Struct*)pack->pBuffer; //Yeahlight: A resurrection request has been made if(srs->rezzopcode == OP_RezzRequest) { Client* client = entity_list.GetClientByName(srs->owner); //Yeahlight: Owner of the corpse is online if(client) { Spell* spell = spells_handler.GetSpellPtr(srs->rez.spellID); //Yeahlight: Spell passed through the packet is a legit spell if(spell) { //Yeahlight: Record the pending resurrection information client->SetPendingRez(true); client->SetPendingRezExp(srs->exp); client->SetPendingCorpseID(srs->corpseDBID); client->SetPendingRezX(srs->rez.x); client->SetPendingRezY(srs->rez.y); client->SetPendingRezZ(srs->rez.z); client->SetPendingRezZone(srs->rez.zoneName); client->SetPendingSpellID(spell->GetSpellID()); client->StartPendingRezTimer(); if(client->GetDebugMe()) client->Message(YELLOW, "Debug: Forwarding the resurrection request to your client (%s)", srs->rez.targetName); //Yeahlight: Forward the resurrection packet to the corpse's owner APPLAYER* outapp = new APPLAYER(OP_RezzRequest, sizeof(Resurrect_Struct)); Resurrect_Struct* rez = (Resurrect_Struct*)outapp->pBuffer; memset(rez, 0, sizeof(Resurrect_Struct)); memcpy(rez, &srs->rez, sizeof(Resurrect_Struct)); client->QueuePacket(outapp); safe_delete(outapp); } } } //Yeahlight: A resurrection confirmation has been made else if(srs->rezzopcode == OP_RezzAnswer) { Client* client = entity_list.GetClientByName(srs->owner); //Yeahlight: Owner of the corpse is online if(client) { bool fullGMRez = false; //Yeahlight: The corpse owner answers 'yes' to the request if(srs->action == 1) { Database::Instance()->SetCorpseRezzed(client->GetPendingCorpseID()); //Yeahlight: Player casted resurrection if(client->GetPendingSpellID() != 994) { float expRefund = 0.00; //Yeahlight: PC has exp on the corpse if(client->GetPendingRezExp()) { //Yeahlight: Switch based on spell ID switch(client->GetPendingSpellID()) { //Yeahlight: Revive case 391: { expRefund = 0.00; break; } //Yeahlight: Resuscitate case 388: { expRefund = 0.50; break; } //Yeahlight: Resurrection case 392: { expRefund = 0.90; break; } //Yeahlight: Reviviscence case 1524: { expRefund = 0.96; break; } //Yeahlight: Convergence case 1733: { expRefund = 0.93; break; } default: { client->Message(RED, "ERROR: Unknown resurrection spell ID: %i", client->GetPendingSpellID()); expRefund = 0.00; } } if(client->GetDebugMe()) client->Message(LIGHTEN_BLUE, "Debug: Your resurrection return on exp: %1.2f", expRefund); client->AddEXP(client->GetPendingRezExp() * expRefund, true); } } //Yeahlight: GM casted resurrection else { fullGMRez = true; if(client->GetDebugMe()) client->Message(LIGHTEN_BLUE, "Debug: Your resurrection return on exp: 1.00"); client->AddEXP(client->GetPendingRezExp(), true); } //Yeahlight: Client is being resurrected in another zone; prepare them for transit if(strcmp(zone->GetShortName(), srs->rez.zoneName) != 0) { client->SetTempHeading(0); client->SetUsingSoftCodedZoneLine(true); client->SetIsZoning(true); client->SetZoningX(client->GetPendingRezX()); client->SetZoningY(client->GetPendingRezY()); client->SetZoningZ(client->GetPendingRezZ()); } //Yeahlight: Send the packet back to the owner of the corpse APPLAYER* outapp = new APPLAYER(OP_RezzComplete, sizeof(Resurrect_Struct)); memcpy(outapp->pBuffer, &srs->rez, sizeof(Resurrect_Struct)); srs->rez.fullGMRez = fullGMRez; client->QueuePacket(outapp); safe_delete(outapp); } //Yeahlight: The corpse owner answers 'no' to the request else if(srs->action == 0) { client->Message(BLACK, "You decline the request to be resurrected."); client->SetPendingRez(false); client->SetPendingRezExp(0); } } } break; } case ServerOP_Uptime: { if (pack->size != sizeof(ServerUptime_Struct)) { cout << "Wrong size on ServerOP_Uptime. Got: " << pack->size << ", Expected: " << sizeof(ServerUptime_Struct) << endl; break; } ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer; int32 ms = Timer::GetCurrentTime(); int32 d = ms / 86400000; ms -= d * 86400000; int32 h = ms / 3600000; ms -= h * 3600000; int32 m = ms / 60000; ms -= m * 60000; int32 s = ms / 1000; if (d) { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02id %02ih %02im %02is", sus->zoneserverid, d, h, m, s); } else if (h) { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02ih %02im %02is", sus->zoneserverid, h, m, s); } else { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02im %02is", sus->zoneserverid, m, s); } break; } case ServerOP_Petition: { cout << "Got Server Requested Petition List Refresh" << endl; ServerPetitionUpdate_Struct* sus = (ServerPetitionUpdate_Struct*) pack->pBuffer; if (sus->status = 0) { petition_list.ReadDatabase(); } else if (sus->status = 1) { petition_list.ReadDatabase(); // Until I fix this to be better.... } break; } case ServerOP_RemoveBoat: // Tazadar (06/12/09) : We remove the boat from the zone { BoatName_Struct* bs = (BoatName_Struct*) pack->pBuffer; cout << "Trying to remove the boat : " << bs->boatname << endl; Mob * tmp = entity_list.GetMob(bs->boatname); if(tmp){ tmp->CastToNPC()->Depop(false); entity_list.RemoveNPC(tmp->CastToNPC()); } break; } case ServerOP_ZoneBoat : // Tazadar (06/16/09) : We teleport player to the other zone ! { cout << "A boat is zoning ! Teleporting clients !" << endl; ZoneBoat_Struct * zb = (ZoneBoat_Struct *) pack->pBuffer; Entity * tmp = 0; Mob * boat = entity_list.GetMob(zb->boatname); float xboat,yboat,zboat,headingboat; if(boat){ xboat = boat->GetX(); yboat = boat->GetY(); zboat = boat->GetZ();; headingboat = boat->GetHeading(); } else{ cerr << "Error in ServerOP_ZoneBoat boat : "<< zb->boatname << " does not exist."<<endl; break; } char * clients = (char *) pack->pBuffer; char zone[16] = ""; strcpy(zone, zb->zonename); char name[30]; float x,y,z,heading; for(int i=0 ; i < zb->numberOfPlayers ; i++){ memcpy(name,clients+sizeof(ZoneBoat_Struct)+30*i,30*sizeof(char)); cout << "Trying to teleport : "<< name << endl; tmp = entity_list.GetClientByName(name); if(tmp != 0 && tmp->IsClient()){ //cout << "ZonePC to " << zone << endl; Client * client = tmp->CastToClient(); heading = client->GetHeading()-headingboat; // Tazadar : Relative heading from the boat z = client->GetZ()-zboat; // Tazadar : Relative z from the boat client->GetRelativeCoordToBoat(client->GetY()-yboat,client->GetX()-xboat,(zb->heading-headingboat)*1.4,y,x); client->SetZoningHeading(zb->heading+heading); client->SetUsingSoftCodedZoneLine(true); client->SetIsZoning(true); client->SetZoningX(zb->x+x); client->SetZoningY(zb->y+y); client->SetZoningZ(zb->z+z); client->ZonePC(zone,0,0,10); } else{ // Tazadar : Player has crashed ? We remove it from boat infos // Tazadar : Make the packet for the World Serv ServerPacket* pack = new ServerPacket(ServerOP_BoatPL, sizeof(ServerBoat_Struct)); ServerBoat_Struct* servBoatInfos = (ServerBoat_Struct*) pack->pBuffer; // Tazadar : Fill the packet memcpy(servBoatInfos->player_name,name,sizeof(servBoatInfos->player_name)); // Tazadar : Send the packet worldserver.SendPacket(pack); } } break; } case ServerOP_SpawnBoat: // Tazadar (06/13/09) : We make the boat spawn before the zone in at the correct location. { SpawnBoat_Struct * bs = (SpawnBoat_Struct *) pack->pBuffer; Mob * tmp = 0; cout << "Spawning the boat :" << bs->boatname << "at loc " << bs->x <<","<< bs->y << "," << bs->z <<" heading " << bs->heading<<endl; //cout << "Loading boat from DB " << endl; string name = bs->boatname; name.resize(name.length()-2); NPCType boat; bool lineroute = false; Database::Instance()->LoadBoatData(name.c_str(),boat,lineroute); NPC* npc = new NPC(&boat, 0, bs->x, bs->y, bs->z, bs->heading); npc->SetLineRoute(lineroute); entity_list.AddNPC(npc); npc->SendPosUpdate(false); break; } case ServerOP_BoatGoTo : // Tazadar (06/14/09) : We make the boat move { BoatGoTo_Struct * gt = (BoatGoTo_Struct *) pack->pBuffer; cout << "World orders " << gt->boatname << " to go to node number " << gt->toNode << endl; Mob * tmp = entity_list.GetMob(gt->boatname); if(tmp && tmp->IsNPC()){ if(tmp->CastToNPC()->IsBoat()){ tmp->CastToNPC()->setBoatDestinationNode(gt->fromNode,gt->toNode); } else{ cerr << "Tried to give an order to the npc "<< gt->boatname <<" which is not a boat " << endl; } } else{ cerr << "Error in ServerOP_BoatGoTo boat " << gt->boatname << " does not exist"<<endl; } break; } case ServerOP_DayTime : // Kibanu - 7/30/2009 : Switch to day time for spawn data { if (ZoneLoaded) zone->SetTimeOfDay(true); break; } case ServerOP_NightTime : // Kibanu - 7/30/2009 : Switch to day time for spawn data { if (ZoneLoaded) zone->SetTimeOfDay(false); break; } case ServerOP_ZoneToZoneRequest: { if(pack->size != sizeof(ZoneToZone_Struct)) break; if (!ZoneLoaded) break; ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer; if(ztz->current_zone_id == zone->GetZoneID()) { // it's a response Entity* entity = entity_list.GetClientByName(ztz->name); if(entity == 0) break; APPLAYER *outapp; outapp = new APPLAYER(OP_ZoneChange,sizeof(ZoneChange_Struct)); ZoneChange_Struct* zc2=(ZoneChange_Struct*)outapp->pBuffer; if(ztz->response == 0 || ztz->response == -1) { zc2->success = ZONE_ERROR_NOTREADY; entity->CastToMob()->SetZone(ztz->current_zone_id); } else { strncpy(zc2->char_name,entity->CastToMob()->GetName(),64); zc2->zoneID=ztz->requested_zone_id; zc2->success = 1; } entity->CastToClient()->QueuePacket(outapp); delete outapp; switch(ztz->response) { case -1: { entity->CastToMob()->Message(RED,"The zone is currently full, please try again later."); break; } case 0: { entity->CastToMob()->Message(RED,"All zone servers are taken at this time, please try again later."); break; } } } else { // it's a request if(zone->GetMaxClients() != 0 && numclients >= zone->GetMaxClients()) ztz->response = -1; else { ztz->response = 1; // since they asked about coming, lets assume they are on their way and not shut down. zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } SendPacket(pack); break; } break; } default: { cout << "Unknown ZSopcode:" << (int)pack->opcode; cout << "size:" << pack->size << endl; //DumpPacket(pack->pBuffer, pack->size); break; } } safe_delete(pack);//delete pack; //Yeahlight: Zone freeze debug if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1) EQC_FREEZE_DEBUG(__LINE__, __FILE__); } return; }