bool Client::BindWound(Mob* bindtar,bool fail){ APPLAYER* bwout_app = new APPLAYER(OP_BindWound,sizeof(BindWound_Struct)); BindWound_Struct* bwout = (BindWound_Struct*)bwout_app->pBuffer; if(!fail){ if(GetFeigned()){ // Break Feign Death for Bind Wound SetFeigned(false); // } int cap = 50; // Set % Cap/Heal Cap int hp_cap = bindtar->GetMaxHP()/2; // if(GetClass() == MONK && GetSkill(BIND_WOUND) > 200){ // cap = 70; // hp_cap += bindtar->GetMaxHP()/5; // } if(!bindwound_timer->Enabled()){ // Begin Bind Wound if(bindtar->GetHP() >= hp_cap){ // INITIAL CAP CHECK Message(DARK_BLUE, "You cannot bandage your target past %d percent of their hit points.", cap); bwout->type = 3; // QueuePacket(bwout_app); // bwout->type = 2; // QueuePacket(bwout_app); // safe_delete(bwout_app); // return true; } int16 bndg_slot = FindItemTypeInInventory(ItemTypeBandage); // Consume Bandage RemoveOneCharge(bndg_slot,true); // bindwound_timer->Start(10000); // Start Timer bindwound_target = bindtar; bwout->type = 3; // Unlock Interface QueuePacket(bwout_app); // bwout->type = 0; // if(!bindtar){ // Target Dead bwout->type = 4; // QueuePacket(bwout_app); // bwout->type = 0; // bindwound_timer->Disable(); // bindwound_target = 0; // } else if(bindtar!=this) // Send Bind Message to target if not binding self bindtar->CastToClient()->Message(DARK_BLUE,"You are being bandaged. Stay relatively still."); } else{ // END Bind Wound bindwound_timer->Disable(); // Stop Timer bindwound_target = 0; if(!bindtar){ // Target Not Found bwout->type = 5; // QueuePacket(bwout_app); // bwout->type = 0; // } if((!GetFeigned() && bindtar->DistNoRoot(this->CastToMob()) <= 400)){ //// **** TAKEN FROM EQEMU, FD Check/Distance? bwout->type = 1; // Finish Bind QueuePacket(bwout_app); // bwout->type = 0; // if(this!=bindtar) // Message to target bindtar->CastToClient()->Message(YELLOW,"The bandaging is complete."); CheckAddSkill(BIND_WOUND); // Check Skill Up if(bindtar->GetHP() < hp_cap){ // END CAP CHECK (Does not include heal amount) int heal = 3; // Set Heal Amount if(GetSkill(BIND_WOUND) > 200) // // heal += GetSkill(BIND_WOUND)*4/10; // // else if(GetSkill(BIND_WOUND) >= 10) // // heal += GetSkill(BIND_WOUND)/4; // // bindtar->SetHP(bindtar->GetHP()+heal); // Set Hp + Update bindtar->SendHPUpdate(); // } else{ // Over Cap Message(DARK_BLUE, "You cannot bandage your target past %d percent of their hit points.", cap); if(this != bindtar) // bindtar->CastToClient()->Message(DARK_BLUE, "You cannot be bandaged past %d percent of your max hit points.",cap); } } else if(bindtar!=this){ // Failed Moved/Moved Away bwout->type = 6; // QueuePacket(bwout_app); // bwout->type = 0; // } else{ //Feigned/Out of Range and binding self Not sure if anything needs to go here or not } } } else if(bindwound_timer->Enabled()){ // Failed: Ended Via Sit/Stand/Feign if(!GetFeigned()){ // Sit/Stand bindwound_timer->Disable(); // bwout->type = 3; // QueuePacket(bwout_app); // bwout->type = 7; // QueuePacket(bwout_app); // } else{ bindwound_timer->Disable(); // Feign Death bindwound_target = 0; // Message(YELLOW,"You have moved and your attempt to bandage has failed."); } } safe_delete(bwout_app); // Delete packet return true; }
void Client::ActivateAA(aaID activate){ if (activate < 0 || activate >= aaHighestID) return; if (IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) return; int AATimerID = GetAATimerID(activate); SendAA_Struct* aa2 = nullptr; aaID aaid = activate; uint8 activate_val = GetAA(activate); //this wasn't taking into acct multi tiered act talents before... if (activate_val == 0){ aa2 = zone->FindAA(activate); if (!aa2){ int i; int a; for (i = 1; i<MAX_AA_ACTION_RANKS; i++){ a = activate - i; if (a <= 0) break; aa2 = zone->FindAA(a); if (aa2 != nullptr) break; } } if (aa2){ aaid = (aaID)aa2->id; activate_val = GetAA(aa2->id); } } if (activate_val == 0){ return; } if (aa2) { if (aa2->account_time_required) { if ((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) { return; } } } if (!p_timers.Expired(&database, AATimerID + pTimerAAStart)) { uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); uint32 aaremain_hr = aaremain / (60 * 60); uint32 aaremain_min = (aaremain / 60) % 60; uint32 aaremain_sec = aaremain % 60; if (aa2) { if (aaremain_hr >= 1) //1 hour or more Message(CC_Red, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", aa2->name, aaremain_hr, aaremain_min, aaremain_sec); else //less than an hour Message(CC_Red, "You can use the ability %s again in %u minute(s) %u seconds", aa2->name, aaremain_min, aaremain_sec); } else { if (aaremain_hr >= 1) //1 hour or more Message(CC_Red, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", aaremain_hr, aaremain_min, aaremain_sec); else //less than an hour Message(CC_Red, "You can use this ability again in %u minute(s) %u seconds", aaremain_min, aaremain_sec); } return; } if (activate_val > MAX_AA_ACTION_RANKS) activate_val = MAX_AA_ACTION_RANKS; activate_val--; //to get array index. //get our current node, now that the indices are well bounded const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; if ((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ Message(CC_Red, "Ability recovery time not yet met."); return; } //everything should be configured out now uint16 target_id = 0; //figure out our target switch (caa->target) { case aaTargetUser: case aaTargetGroup: target_id = GetID(); break; case aaTargetCurrent: case aaTargetCurrentGroup: if (GetTarget() == nullptr) { Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! p_timers.Clear(&database, AATimerID + pTimerAAStart); return; } target_id = GetTarget()->GetID(); break; case aaTargetPet: if (GetPet() == nullptr) { Message(0, "A pet is required for this skill."); return; } target_id = GetPetID(); break; } //handle non-spell action if (caa->action != aaActionNone) { if (caa->mana_cost > 0) { if (GetMana() < caa->mana_cost) { Message_StringID(CC_Red, INSUFFICIENT_MANA); return; } SetMana(GetMana() - caa->mana_cost); } if (caa->reuse_time > 0) { uint32 timer_base = CalcAAReuseTimer(caa); if (activate == aaImprovedHarmTouch || activate == aaLeechTouch) { p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); } p_timers.Start(AATimerID + pTimerAAStart, timer_base); SendAATimer(activate, static_cast<uint32>(time(nullptr)), static_cast<uint32>(time(nullptr))); } HandleAAAction(aaid); } //cast the spell, if we have one if (caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { if (caa->reuse_time > 0) { uint32 timer_base = CalcAAReuseTimer(caa); SendAATimer(activate, static_cast<uint32>(time(nullptr)), static_cast<uint32>(time(nullptr))); p_timers.Start(AATimerID + pTimerAAStart, timer_base); if (activate == aaImprovedHarmTouch || activate == aaLeechTouch) { p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); } // Bards can cast instant cast AAs while they are casting another song if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if (!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { //Reset on failed cast SendAATimer(activate, 0, 0xFFFFFF); Message_StringID(CC_Yellow, ABILITY_FAILED); p_timers.Clear(&database, AATimerID + pTimerAAStart); return; } } else { if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { //Reset on failed cast SendAATimer(activate, 0, 0xFFFFFF); Message_StringID(CC_Yellow, ABILITY_FAILED); p_timers.Clear(&database, AATimerID + pTimerAAStart); return; } } } else { if (!CastSpell(caa->spell_id, target_id)) return; } } }
int32 Client::LevelRegen() { bool sitting = IsSitting(); bool feigned = GetFeigned(); int level = GetLevel(); bool bonus = GetRaceBitmask(GetBaseRace()) & RuleI(Character, BaseHPRegenBonusRaces); uint8 multiplier1 = bonus ? 2 : 1; int32 hp = 0; //these calculations should match up with the info from Monkly Business, which was last updated ~05/2008: http://www.monkly-business.net/index.php?pageid=abilities if (level < 51) { if (sitting) { if (level < 20) hp += 2 * multiplier1; else if (level < 50) hp += 3 * multiplier1; else //level == 50 hp += 4 * multiplier1; } else //feigned or standing hp += 1 * multiplier1; } //there may be an easier way to calculate this next part, but I don't know what it is else { //level >= 51 int32 tmp = 0; float multiplier2 = 1; if (level < 56) { tmp = 2; if (bonus) multiplier2 = 3; } else if (level < 60) { tmp = 3; if (bonus) multiplier2 = 3.34; } else if (level < 61) { tmp = 4; if (bonus) multiplier2 = 3; } else if (level < 63) { tmp = 5; if (bonus) multiplier2 = 2.8; } else if (level < 65) { tmp = 6; if (bonus) multiplier2 = 2.67; } else { //level >= 65 tmp = 7; if (bonus) multiplier2 = 2.58; } hp += int32(float(tmp) * multiplier2); if (sitting) hp += 3 * multiplier1; else if (feigned) hp += 1 * multiplier1; } return hp; }
//o-------------------------------------------------------------- //| Name: GetFactionLevel; rembrant, Dec. 16, 2001 //o-------------------------------------------------------------- //| Notes: Gets the characters faction standing with the //| specified NPC. //| Will return Indifferent on failure. //o-------------------------------------------------------------- FACTION_VALUE Client::GetFactionLevel(int32 char_id, int32 npc_id, int32 p_race, int32 p_class, int32 p_deity, sint32 pFaction, Mob* tnpc) { if (pFaction < 0) return GetSpecialFactionCon(tnpc); FACTION_VALUE fac = FACTION_INDIFFERENT; //sint32 pFacValue; -Trumpcard: commenting. Not currently used. sint32 tmpFactionValue; FactionMods fmods; // neotokyo: few optimizations if (GetFeigned()) return FACTION_INDIFFERENT; if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead()) return FACTION_INDIFFERENT; if (IsInvisible(tnpc)) return FACTION_INDIFFERENT; if (tnpc && tnpc->GetOwnerID() != 0) // neotokyo: pets always con indiff return FACTION_INDIFFERENT; #ifdef GUILDWARS if(tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->GetGuildOwner() != 0 && GuildDBID() != 0) { if(IsAttackAllowed(tnpc)) return FACTION_SCOWLS; else return FACTION_ALLY; } #endif //First get the NPC's Primary faction if(pFaction > 0) { //Get the faction data from the database if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction)) { //Get the players current faction with pFaction tmpFactionValue = this->GetCharacterFactionLevel(pFaction); //Return the faction to the client fac = CalculateFaction(&fmods, tmpFactionValue); //Message(0,"Faction: %i %i %i %i",fmods.base,fmods.class_mod,fmods.race_mod,fmods.deity_mod); //Message(0,"tmpFactionValue: %i, fac: %i",tmpFactionValue,fac); } } else { fmods.base = 0; fmods.deity_mod = 0; if (tnpc && p_class == (int32) tnpc->GetClass()%16) fmods.class_mod = 301; else if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType == 0) fmods.class_mod = -101; else fmods.class_mod = 0; if (tnpc && IsOfEqualRace(p_race, tnpc->GetRace()) ) fmods.race_mod = 101; else if (tnpc && IsOfIndiffRace(p_race, tnpc->GetRace()) ) fmods.race_mod = 0; else if (tnpc) fmods.race_mod = -51; else fmods.race_mod = 0; fac = CalculateFaction(&fmods, 0); } // merchant fix if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType && (fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) fac = FACTION_DUBIOUS; if (tnpc != 0 && fac != FACTION_SCOWLS && tnpc->CastToNPC()->CheckAggro(this)) fac = FACTION_THREATENLY; return fac; }