void Vehicle::RegeneratePower(Powers power) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); if (curValue >= maxValue) return; float addvalue = 0.0f; // hack: needs more research of power type from the dbc. // It must contains some info about vehicles like Salvaged Chopper. if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE) return; addvalue = 10.0f; ModifyPower(power, (int32)addvalue); for(int i =0; i != MAX_SEAT; i++) { if(Unit *pPassanger = GetPassenger(i)) { if(pPassanger->GetTypeId() == TYPEID_PLAYER) SendCreateUpdateToPlayer((Player*)pPassanger); } } }
void Vehicle::RegeneratePower(Powers power) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); if (curValue >= maxValue) return; float addvalue = 0.0f; // hack: needs more research of power type from the dbc. // It must contains some info about vehicles like Salvaged Chopper. if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE) return; addvalue = 10.0; ModifyPower(power, (int32)addvalue); WorldPacket data(SMSG_POWER_UPDATE); data << GetPackGUID(); data << uint8(power); data << uint32(addvalue+curValue); SendMessageToSet(&data, true); }
double MapAnalysis::GetPowerRank(const CityData * city) const { Assert(city); PLAYER_INDEX owner = city->GetOwner(); double power = GetPower(owner, city->GetHomeCity().RetPos()); double max_power = GetMaxPower(owner); return (max_power > 0.0) ? (power / max_power) : 0.0; }
void GuardianSummon::Load(CreatureProto* proto, Unit* owner, LocationVector & position, uint32 spellid, int32 summonslot) { Summon::Load(proto, owner, position, spellid, summonslot); SetPowerType(POWER_TYPE_MANA); SetMaxPower(POWER_TYPE_MANA, GetMaxPower(POWER_TYPE_MANA) + 28 + 10 * getLevel()); SetPower(POWER_TYPE_MANA, GetPower(POWER_TYPE_MANA) + 28 + 10 * getLevel()); setLevel(owner->getLevel()); SetMaxHealth(GetMaxHealth() + 28 + 30 * getLevel()); SetHealth(GetMaxHealth()); SetType(CREATURE_TYPE_GUARDIAN); m_aiInterface->Init(this, AITYPE_PET , MOVEMENTTYPE_NONE, owner); m_aiInterface->SetUnitToFollow(owner); m_aiInterface->SetFollowDistance(3.0f); m_noRespawn = true; }
void Vehicle::RegeneratePower(Powers power) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); if (curValue >= maxValue) return; float addvalue = 0.0f; // hack: needs more research of power type from the dbc. // It must contains some info about vehicles like Salvaged Chopper. if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE) return; addvalue = 20.0f; ModifyPower(power, (int32)addvalue); }
void Creature::RegenerateMana() { uint32 curValue = GetPower(POWER_MANA); uint32 maxValue = GetMaxPower(POWER_MANA); if (curValue >= maxValue) return; float ManaIncreaseRate = sWorld.getRate(RATE_POWER_MANA); float Spirit = GetStat(STAT_SPIRIT); if( ManaIncreaseRate <= 0 ) ManaIncreaseRate = 1; uint32 addvalue = 0; if (isInCombat() || isPet()) addvalue = uint32((Spirit/5 + 17) * ManaIncreaseRate); else addvalue = maxValue/3; ModifyPower(POWER_MANA, addvalue); }
void Creature::Regenerate(Powers power) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); if (curValue >= maxValue) return; float addvalue = 0.0f; switch (power) { case POWER_FOCUS: { // For hunter pets. addvalue = 24 * sWorld->getRate(RATE_POWER_FOCUS); break; } case POWER_ENERGY: { // For deathknight's ghoul. addvalue = 20; break; } default: return; } // Apply modifiers (if any). AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if (Powers((*i)->GetMiscValue()) == power) AddPctN(addvalue, (*i)->GetAmount()); addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (isHunterPet()? PET_FOCUS_REGEN_INTERVAL : CREATURE_REGEN_INTERVAL) / (5 * IN_MILLISECONDS); ModifyPower(power, int32(addvalue)); }
bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool current) { m_loading = true; uint32 ownerid = owner->GetGUIDLow(); QueryResult result; if (petnumber) // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND id = '%u'", ownerid, petnumber); else if (current) // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND slot = '%u'", ownerid, PET_SAVE_AS_CURRENT); else if (petentry) // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid, petentry, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT); else // any current or other non-stabled pet (for hunter "call pet") // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT); if (!result) { m_loading = false; return false; } Field* fields = result->Fetch(); // update for case of current pet "slot = 0" petentry = fields[1].GetUInt32(); if (!petentry) return false; uint32 summon_spell_id = fields[15].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) return false; PetType pet_type = PetType(fields[16].GetUInt8()); if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); if (!creatureInfo || !creatureInfo->isTameable(owner->CanTameExoticPets())) return false; } uint32 pet_number = fields[0].GetUInt32(); if (current && owner->IsPetNeedBeTemporaryUnsummoned()) { owner->SetTemporaryUnsummonedPetNumber(pet_number); return false; } Map* map = owner->GetMap(); uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET); if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number)) return false; float px, py, pz; owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } setPetType(pet_type); setFaction(owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); CreatureTemplate const* cinfo = GetCreatureInfo(); if (cinfo->type == CREATURE_TYPE_CRITTER) { map->AddToMap(this->ToCreature()); return true; } m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner)); SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt16(); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); SetName(fields[8].GetString()); switch (getPetType()) { case SUMMON_PET: petlevel = owner->getLevel(); SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus SetSheath(SHEATH_STATE_MELEE); SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); setPowerType(POWER_FOCUS); break; default: if (!IsPetGhoul()) sLog->outError("Pet have incorrect type (%u) for pet loading.", getPetType()); break; } SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here SetCreatorGUID(owner->GetGUID()); InitStatsForLevel(petlevel); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); SynchronizeLevelWithOwner(); SetReactState(ReactStates(fields[6].GetUInt8())); SetCanModifyStats(true); if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); else { uint32 savedhealth = fields[10].GetUInt32(); uint32 savedmana = fields[11].GetUInt32(); if (!savedhealth && getPetType() == HUNTER_PET) setDeathState(JUST_DIED); else { SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); } } // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (fields[7].GetUInt8()) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'", PET_SAVE_NOT_IN_SLOT, ownerid, PET_SAVE_AS_CURRENT, m_charmInfo->GetPetNumber()); trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'", PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber()); CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? if (summon_spell_id) { WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2)); data.append(owner->GetPackGUID()); data.append(owner->GetPackGUID()); data << uint8(0); data << uint32(summon_spell_id); data << uint32(256); // CAST_FLAG_UNKNOWN3 data << uint32(0); owner->SendMessageToSet(&data, true); } owner->SetMinion(this, true); map->AddToMap(this->ToCreature()); InitTalentForLevel(); // set original talents points before spell loading uint32 timediff = uint32(time(NULL) - fields[14].GetUInt32()); _LoadAuras(timediff); // load action bar, if data broken will fill later by default spells. if (!is_temporary_summoned) { m_charmInfo->LoadPetActionBar(fields[13].GetString()); _LoadSpells(); InitTalentForLevel(); // re-init to check talent count _LoadSpellCooldowns(); LearnPetPassives(); InitLevelupSpellsForLevel(); CastPetAuras(current); } CleanupActionBar(); // remove unknown spells from action bar after load sLog->outDebug(LOG_FILTER_PETS, "New Pet has guid %u", GetGUIDLow()); owner->PetSpellInitialize(); if (owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_PET); owner->SendTalentsInfoData(true); if (getPetType() == HUNTER_PET) { result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", owner->GetGUIDLow(), GetCharmInfo()->GetPetNumber()); if (result) { delete m_declinedname; m_declinedname = new DeclinedName; Field* fields2 = result->Fetch(); for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { m_declinedname->name[i] = fields2[i].GetString(); } } } //set last used pet number (for use in BG's) if (owner->GetTypeId() == TYPEID_PLAYER && isControlled() && !isTemporarySummoned() && (getPetType() == SUMMON_PET || getPetType() == HUNTER_PET)) owner->ToPlayer()->SetLastPetNumber(pet_number); m_loading = false; return true; }
// TODO: Move stat mods code to pet passive auras bool Guardian::InitStatsForLevel(uint8 petlevel) { CreatureTemplate const* cinfo = GetCreatureInfo(); ASSERT(cinfo); SetLevel(petlevel); //Determine pet type PetType petType = MAX_PET_TYPE; if (isPet() && m_owner->GetTypeId() == TYPEID_PLAYER) { if ((m_owner->getClass() == CLASS_WARLOCK) || (m_owner->getClass() == CLASS_SHAMAN) // Fire Elemental || (m_owner->getClass() == CLASS_DEATH_KNIGHT)) // Risen Ghoul petType = SUMMON_PET; else if (m_owner->getClass() == CLASS_HUNTER) { petType = HUNTER_PET; m_unitTypeMask |= UNIT_MASK_HUNTER_PET; } else sLog->outError("Unknown type pet %u is summoned by player class %u", GetEntry(), m_owner->getClass()); } uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry; SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50)); SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME); SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME); SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); //scale CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family); if (cFamily && cFamily->minScale > 0.0f && petType == HUNTER_PET) { float scale; if (getLevel() >= cFamily->maxScaleLevel) scale = cFamily->maxScale; else if (getLevel() <= cFamily->minScaleLevel) scale = cFamily->minScale; else scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } // Resistance for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); //health, mana, armor and resistance PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel); if (pInfo) // exist in DB { SetCreateHealth(pInfo->health); if (petType != HUNTER_PET) //hunter pet use focus SetCreateMana(pInfo->mana); if (pInfo->armor > 0) SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); for (uint8 stat = 0; stat < MAX_STATS; ++stat) SetCreateStat(Stats(stat), float(pInfo->stats[stat])); } else // not exist in DB, use some default fake data { // remove elite bonuses included in DB values CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class); SetCreateHealth(stats->BaseHealth[cinfo->expansion]); SetCreateMana(stats->BaseMana); SetCreateStat(STAT_STRENGTH, 22); SetCreateStat(STAT_AGILITY, 22); SetCreateStat(STAT_STAMINA, 25); SetCreateStat(STAT_INTELLECT, 28); SetCreateStat(STAT_SPIRIT, 27); } SetBonusDamage(0); switch (petType) { case SUMMON_PET: { //the damage bonus used for pets is either fire or shadow damage, whatever is higher uint32 fire = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE); uint32 shadow = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW); uint32 val = (fire > shadow) ? fire : shadow; SetBonusDamage(int32 (val * 0.15f)); //bonusAP += val * 0.57; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); break; } case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32(sObjectMgr->GetXPForLevel(petlevel)*PET_XP_FACTOR)); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); //damage range is then petlevel / 2 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); //damage is increased afterwards as strength and pet scaling modify attack power break; } default: { switch (GetEntry()) { case 510: // mage Water Elemental { SetBonusDamage(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); break; } case 1964: //force of nature { if (!pInfo) SetCreateHealth(30 + 30*petlevel); float bonusDmg = m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_NATURE) * 0.15f; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2) + bonusDmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2) + bonusDmg)); break; } case 15352: //earth elemental 36213 { if (!pInfo) SetCreateHealth(100 + 120*petlevel); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } case 15438: //fire elemental { if (!pInfo) { SetCreateHealth(40*petlevel); SetCreateMana(28 + 10*petlevel); } SetBonusDamage(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FIRE) * 0.5f); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel)); break; } case 19668: // Shadowfiend { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } int32 bonus_dmg = (int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_SHADOW)* 0.3f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + bonus_dmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + bonus_dmg)); break; } case 19833: //Snake Trap - Venomous Snake { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel / 2) - 25)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel / 2) - 18)); break; } case 19921: //Snake Trap - Viper { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel / 2 - 10)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel / 2)); break; } case 29264: // Feral Spirit { if (!pInfo) SetCreateHealth(30*petlevel); float dmg_multiplier = 0.3f; if (m_owner->GetAuraEffect(63271, 0)) // Glyph of Feral Spirit dmg_multiplier = 0.6f; SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier)); // 14AP == 1dps, wolf's strike speed == 2s so dmg = basedmg + AP / 14 * 2 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(m_owner->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor) SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(m_owner->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina) if (!HasAura(58877))//prevent apply twice for the 2 wolves AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done. break; } case 31216: // Mirror Image { SetBonusDamage(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); SetDisplayId(m_owner->GetDisplayId()); if (!pInfo) { SetCreateMana(28 + 30*petlevel); SetCreateHealth(28 + 10*petlevel); } break; } case 27829: // Ebon Gargoyle { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } } break; } } UpdateAllStats(); SetFullHealth(); SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); return true; }
float Bazooka::Shot(Game_Manager* gm_, Unit* User_, int team_, const coord_def& start_, const coord_def& pos_, float focus_) { float angle_ = GetAngleToTarget(start_, pos_); if(UseBullet(1)) { for(int i = 0;i<bunch;i++) { float focus2_ = rand_float(-focus_, focus_, "Bazooka::Shot focus"); float speed2_ = shot_speed*GetShotSpeedApply(); float damage_ = damage*GetDamegeApply()*(User_?User_->GetAtkApply():1.0f); gm_->shot_list.push_back(new Shot_missile(&tex_missile, User_, damage_, GetPower(), GetMaxPower(), range, team_, start_, angle_+focus2_, speed2_, guided_range, guided_power, GetDistance())); } if (gm_->isPlayerCanHear(GetPos())) { PlaySE(se_rocket, false); } gm_->Noise(team_,start_,GetNoise() * User_->GetSilencer()); return burst_speed*(1.0f/(GetBurstSpeedApply()*(User_?User_->GetAtkSpdApply():1.0f))); } return -1; }
float Sniper::Shot(Game_Manager* gm_, Unit* User_, int team_, const coord_def& start_, const coord_def& pos_, float focus_) { float angle_ = GetAngleToTarget(start_, pos_); if(UseBullet(1)) { for(int i = 0;i<bunch;i++) { float focus2_ = rand_float(-focus_, focus_,"Sniper::Shot focus"); if(User_->GetSniper()) focus2_ = 0; float speed2_ = shot_speed*GetShotSpeedApply()*rand_float(0.8f, 1.2f, "Sniper::Shot speed"); float damage_ = damage*GetDamegeApply()*(User_?User_->GetAtkApply():1.0f); gm_->shot_list.push_back(new Shot_sniper(&tex_gun, User_, damage_, sniper, GetPower(), GetMaxPower(), team_, start_, angle_+focus2_, GetDistance(), 50)); } if (gm_->isPlayerCanHear(GetPos())) { if(GetType() == WT_SILENCE || User_->GetSilencer() != 1.0f) PlaySE(se_silencesnipergun); else PlaySE(se_snipergun); } gm_->Noise(team_,start_,GetNoise() * User_->GetSilencer()); return burst_speed*(1.0f/(GetBurstSpeedApply()*(User_?User_->GetAtkSpdApply():1.0f))); } return -1; }
void Player::UpdateManaRegen() { // Mana regen from spirit float spirit_regen = OCTRegenMPPerSpirit(); spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); float HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; float combat_regen = 0.004f * GetMaxPower(POWER_MANA) + spirit_regen + (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f); float base_regen = 0.004f * GetMaxPower(POWER_MANA) + (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f); if (getClass() == CLASS_WARLOCK) { combat_regen = 0.01f * GetMaxPower(POWER_MANA) + spirit_regen + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA); base_regen = 0.01f * GetMaxPower(POWER_MANA) + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA); } // Mana Meditation && Meditation if (HasAuraType(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT)) base_regen += 0.5 * spirit_regen; // Allows 50% of your mana regeneration from Spirit to continue while in combat. // Rune of Power : Increase Mana regeneration by 100% if (HasAura(116014)) { combat_regen *= 2; base_regen *= 2; } // Incanter's Ward : Increase Mana regen by 65% if (HasAura(118858)) { combat_regen *= 1.65f; base_regen *= 1.65f; } // Chaotic Energy : Increase Mana regen by 625% if (HasAura(111546)) { // haste also increase your mana regeneration HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; combat_regen = combat_regen + (combat_regen * 6.25f); combat_regen *= HastePct; base_regen = base_regen + (base_regen * 6.25f); base_regen *= HastePct; } // Nether Attunement - 117957 : Haste also increase your mana regeneration if (HasAura(117957)) { HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; combat_regen *= HastePct; base_regen *= HastePct; } // Mana Attunement : Increase Mana regen by 50% if (HasAura(121039)) { combat_regen = combat_regen + (combat_regen * 0.5f); combat_regen *= HastePct; base_regen = base_regen + (base_regen * 0.5f); base_regen *= HastePct; } // Invocation : Decrease your mana regen by 50% if (HasAura(114003)) { combat_regen *= 0.5f; base_regen *= 0.5f; } // Not In Combat : 2% of base mana + spirit_regen SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen); // In Combat : 2% of base mana SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, combat_regen); }
float Melee_AssasinKnife::Shot(Game_Manager* gm_, Unit* User_, int team_, const coord_def& start_, const coord_def& pos_, float focus_) { if (gm_->isPlayerCanHear(GetPos())) { PlaySE(se_assknife); } float angle_ = GetAngleToTarget(start_, pos_); float damage_ = damage*GetDamegeApply()*(User_?User_->GetAtkApply():1.0f); gm_->shot_list.push_back(new Shot_assasinknife(width<3.0f?effect_texture:&tex_melee2, User_, damage_, GetPower(), GetMaxPower(), burst_speed, team_, start_, angle_, GetDistance(), width, back_stab)); return burst_speed*(1.0f/(GetBurstSpeedApply()*(User_?User_->GetAtkSpdApply():1.0f))); }
void CActorCondition::UpdateTutorialThresholds() { string256 cb_name; static float _cPowerThr = pSettings->r_float("tutorial_conditions_thresholds","power"); static float _cPowerMaxThr = pSettings->r_float("tutorial_conditions_thresholds","max_power"); static float _cBleeding = pSettings->r_float("tutorial_conditions_thresholds","bleeding"); static float _cSatiety = pSettings->r_float("tutorial_conditions_thresholds","satiety"); static float _cRadiation = pSettings->r_float("tutorial_conditions_thresholds","radiation"); static float _cWpnCondition = pSettings->r_float("tutorial_conditions_thresholds","weapon_jammed"); static float _cPsyHealthThr = pSettings->r_float("tutorial_conditions_thresholds","psy_health"); bool b = true; if(b && !m_condition_flags.test(eCriticalPowerReached) && GetPower()<_cPowerThr){ m_condition_flags.set (eCriticalPowerReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_critical_power"); } if(b && !m_condition_flags.test(eCriticalMaxPowerReached) && GetMaxPower()<_cPowerMaxThr){ m_condition_flags.set (eCriticalMaxPowerReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_critical_max_power"); } if(b && !m_condition_flags.test(eCriticalBleedingSpeed) && BleedingSpeed()>_cBleeding){ m_condition_flags.set (eCriticalBleedingSpeed, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_bleeding"); } if(b && !m_condition_flags.test(eCriticalSatietyReached) && GetSatiety()<_cSatiety){ m_condition_flags.set (eCriticalSatietyReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_satiety"); } if(b && !m_condition_flags.test(eCriticalRadiationReached) && GetRadiation()>_cRadiation){ m_condition_flags.set (eCriticalRadiationReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_radiation"); } if(b && !m_condition_flags.test(ePhyHealthMinReached) && GetPsyHealth()<_cPsyHealthThr){ m_condition_flags.set (ePhyHealthMinReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_psy"); } if(b && m_condition_flags.test(eCantWalkWeight) && !m_condition_flags.test(eCantWalkWeightReached)){ m_condition_flags.set (eCantWalkWeightReached, TRUE); b=false; xr_strcpy(cb_name,"_G.on_actor_cant_walk_weight"); } if(b && !m_condition_flags.test(eWeaponJammedReached)&&m_object->inventory().GetActiveSlot()!=NO_ACTIVE_SLOT){ PIItem item = m_object->inventory().ItemFromSlot(m_object->inventory().GetActiveSlot()); CWeapon* pWeapon = smart_cast<CWeapon*>(item); if(pWeapon&&pWeapon->GetCondition()<_cWpnCondition){ m_condition_flags.set (eWeaponJammedReached, TRUE);b=false; xr_strcpy(cb_name,"_G.on_actor_weapon_jammed"); } } if(!b){ luabind::functor<LPCSTR> fl; R_ASSERT (ai().script_engine().functor<LPCSTR>(cb_name,fl)); fl (); } }
void CActorCondition::UpdateCondition() { if(psActorFlags.test(AF_GODMODE_RT)) { UpdateSatiety(); UpdateBoosters(); m_fAlcohol += m_fV_Alcohol*m_fDeltaTime; clamp (m_fAlcohol, 0.0f, 1.0f); if(IsGameTypeSingle()) { CEffectorCam* ce = Actor()->Cameras().GetCamEffector((ECamEffectorType)effAlcohol); if(ce) RemoveEffector(m_object,effAlcohol); } } if (GodMode()) return; if (!object().g_Alive()) return; if (!object().Local() && m_object != Level().CurrentViewEntity()) return; float base_weight = object().MaxCarryWeight(); float cur_weight = object().inventory().TotalWeight(); if ((object().mstate_real&mcAnyMove)) { ConditionWalk( cur_weight / base_weight, isActorAccelerated( object().mstate_real,object().IsZoomAimingMode() ), (object().mstate_real&mcSprint) != 0 ); } else { ConditionStand( cur_weight / base_weight ); } if ( IsGameTypeSingle() ) { float k_max_power = 1.0f; if( true ) { k_max_power = 1.0f + _min(cur_weight, base_weight) / base_weight + _max(0.0f, (cur_weight - base_weight) / 10.0f); } else { k_max_power = 1.0f; } SetMaxPower (GetMaxPower() - m_fPowerLeakSpeed * m_fDeltaTime * k_max_power); } m_fAlcohol += m_fV_Alcohol*m_fDeltaTime; clamp (m_fAlcohol, 0.0f, 1.0f); if ( IsGameTypeSingle() ) { CEffectorCam* ce = Actor()->Cameras().GetCamEffector((ECamEffectorType)effAlcohol); if ((m_fAlcohol>0.0001f) ){ if(!ce){ AddEffector(m_object,effAlcohol, "effector_alcohol", GET_KOEFF_FUNC(this, &CActorCondition::GetAlcohol)); } }else{ if(ce) RemoveEffector(m_object,effAlcohol); } string512 pp_sect_name; shared_str ln = Level().name(); if(ln.size()) { CEffectorPP* ppe = object().Cameras().GetPPEffector((EEffectorPPType)effPsyHealth); strconcat (sizeof(pp_sect_name),pp_sect_name, "effector_psy_health", "_", *ln); if(!pSettings->section_exist(pp_sect_name)) xr_strcpy (pp_sect_name, "effector_psy_health"); if ( !fsimilar(GetPsyHealth(), 1.0f, 0.05f) ) { if(!ppe) { AddEffector(m_object,effPsyHealth, pp_sect_name, GET_KOEFF_FUNC(this, &CActorCondition::GetPsy)); } }else { if(ppe) RemoveEffector(m_object,effPsyHealth); } } //- if(fis_zero(GetPsyHealth())) //- SetHealth( 0.0f ); }; UpdateSatiety(); UpdateBoosters(); inherited::UpdateCondition(); if( IsGameTypeSingle() ) UpdateTutorialThresholds(); if(GetHealth()<0.05f && m_death_effector==NULL && IsGameTypeSingle()) { if(pSettings->section_exist("actor_death_effector")) m_death_effector = xr_new<CActorDeathEffector>(this, "actor_death_effector"); } if(m_death_effector && m_death_effector->IsActual()) { m_death_effector->UpdateCL (); if(!m_death_effector->IsActual()) m_death_effector->Stop(); } AffectDamage_InjuriousMaterialAndMonstersInfluence(); }