PDA

View Full Version : Random fixes


Branks
08-01-2004, 02:41 PM
hi, ive kinda made it a goal of mine to fix AA as a means of learning to program, im posting so that anyone else thats been working on them as well may post their progress so i dont have to do something thats already been done, and so that others may notice problems in what ive corrected so far.

anyway ive corrected quite a few but i need some help on the more complex ones such as wake the dead and doppelganger, so im hoping someone else may have already made some progress on those or others and would like to share.

also let me say sorry for deleting the exsisting comments in eq_packet_structs.h as ive been useing that as a checklist of sorta, also while working with these i discovered a tons of little errors and exploits, the biggest of which were that the entire AA table was off by one so checks for innate STA were actually checking innate STR, also with the way AA were set up i found a huge exploit allowing any character to have any AA skill at any time, thats been corrected however another huge problem is that the AA timers dont seem to be working at all, so i need to ask if they ever were to begin with or maybe my database or something ive done has broken them, these all work with the latest CVS 07-31-04 and the latest spells_us.txt from sony, although some of the spells themselves arent correct so druid dire charm does not check if the target is an animal, can correct this in your own spells_us.txt or ill eventually do it in the code for the skill itself i guess.

PROS- most targeted AAs work, if your database is setup correctly with the correct max level and the cost of the FIRST purchase of a skill the buy ammount is correct in that it doubles when needed 2-4-6 etc, i fixed the exploit i found. i also threw in the timer mods for skill reuse AAs, and i put in a message to client for my own testing purposes so youll have to delete those as needed

CONS- THIS WILL DELETE ALL EXSISTING AA SKILLS AND POINTS FROM ALL CHARACTERS on your server, and none are really usefull to legit servers since currently the AA timer is not working, for me atleast

uhh also im not sure how to post all this without it useing word wrap or whatever so this might be messy but oh well...

zone\command.cpp around line 4748
replace exsisintg with-


void command_manaburn(Client *c, const Seperator *sep)
{
Mob* target=c->GetTarget();

if (c->GetTarget() == 0)
c->Message(0, "#Manaburn needs a target.");
else {
int cur_level=c->GetAAStruct()->god_ability.named.mana_burn;
if (c->DistNoRootNoZ(*target) > 200)
c->Message(0,"You are too far away from your target.");
else {
if(cur_level == 1) {
if(c->IsAttackAllowed(target))
{
int nukedmg=(c->GetMana())*2;
if (nukedmg>0)
{
target->Damage(c, nukedmg, 2751,240);
c->SetMana(0);
}
LogFile->write(EQEMuLog::Normal,"Manaburn request from %s, damage: %d", c->GetName(), nukedmg);
}
}
else
c->Message(0, "You have not learned this skill.");
}
}
}



common\eq_packet_structs.h around line 3142
replace exsisintg with-


// New Alternate Advancement table. holds all the skill levels for the AA skills.
// Length: 309 Bytes
// OpCode: 1422
struct PlayerAA_Struct {
/* 0 */ uint8 unknown0;
union {
uint8 unnamed[17];
struct {
/* 1 */ uint8 innate_strength; //works
/* 2 */ uint8 innate_stamina; //works
/* 3 */ uint8 innate_agility; //works
/* 4 */ uint8 innate_dexterity; //works
/* 5 */ uint8 innate_intelligence; //works
/* 6 */ uint8 innate_wisdom; //works
/* 7 */ uint8 innate_charisma; //works
/* 8 */ uint8 innate_fire_protection; //works

/* 9 */ uint8 innate_cold_protection; //works
/* 10 */ uint8 innate_magic_protection; //works
/* 11 */ uint8 innate_poison_protection; //works
/* 12 */ uint8 innate_disease_protection; //works
/* 13 */ uint8 innate_run_speed; //works, 3 levs
/* 14 */ uint8 unknown14; //was regeneration
/* 15 */ uint8 innate_metabolism; //dont know, 3 levs
/* 16 */ uint8 innate_lung_capacity; //dont know, 3 levs
/* 17 */ uint8 first_aid; //dont know, 3 levs
} named;
} general_skills;
union {
uint8 unnamed[17];
struct {
/* 18 */ uint8 healing_adept; //works
/* 19 */ uint8 healing_gift; //works
/* 20 */ uint8 spell_casting_mastery; //dont know,
/* 21 */ uint8 spell_casting_reinforcement; //dont know,
/* 22 */ uint8 unknown22; //was mental clarity
/* 23 */ uint8 spell_casting_fury; //works
/* 24 */ uint8 chanelling_focus; //dont know,
/* 25 */ uint8 spell_casting_subtlety; //dont know,
/* 26 */ uint8 spell_casting_expertise; //dont know,
/* 27 */ uint8 spell_casting_deftness; //works
/* 28 */ uint8 natural_durability; //works
/* 29 */ uint8 natural_healing; //works
/* 30 */ uint8 combat_fury; //dont know,
/* 31 */ uint8 fear_resistance; //works
/* 32 */ uint8 finishing_blow; //dont know,
/* 33 */ uint8 combat_stability; //dont know,
/* 34 */ uint8 combat_agility; //dont know,
} named;
} archetype_skills;
union {
uint8 unnamed[94];
struct {
/* 35 */ uint8 mass_group_buff; //works lil off
// ===== Cleric =====
/* 36 */ uint8 divine_resurrection; //works
/* 37 */ uint8 innate_invis_to_undead; //works
/* 38 */ uint8 celestial_regeneration; //works
/* 39 */ uint8 bestow_divine_aura; //works
/* 40 */ uint8 turn_undead; //Spell Buggy
/* 41 */ uint8 purify_soul; //works but buggy
// ===== Druid =====
/* 42 */ uint8 quick_evacuation; //works
/* 43 */ uint8 exodus; //works
/* 44 */ uint8 quick_damage; //works
/* 45 */ uint8 enhanced_root; //dont know
/* 46 */ uint8 dire_charm; //works lil off
// ===== Shaman =====
/* 47 */ uint8 cannibalization; //works
/* 48 */ uint8 quick_buff; //dont know, 3 levs
/* 49 */ uint8 alchemy_mastery; //dont know
/* 50 */ uint8 rabid_bear; //works
// ===== Wizard =====
/* 51 */ uint8 unknown51; //used to be manaburn
/* 52 */ uint8 improved_familiar; //works
/* 53 */ uint8 nexus_gate; //works
// ===== Enchanter =====
/* 54 */ uint8 unknown54;
/* 55 */ uint8 permanent_illusion; //dont know
/* 56 */ uint8 jewel_craft_mastery; //dont know, 3 levs
/* 57 */ uint8 gather_mana; //works
// ===== Mage =====
/* 58 */ uint8 mend_companion; //Works
/* 59 */ uint8 quick_summoning; //dont know
/* 60 */ uint8 frenzied_burnout; //not working-spell buggy
/* 61 */ uint8 elemental_form_fire; //Works
/* 62 */ uint8 elemental_form_water; //Works
/* 63 */ uint8 elemental_form_earth; //Works
/* 64 */ uint8 elemental_form_air; //Works
/* 65 */ uint8 unknown65; //was improved reclaim energy
/* 66 */ uint8 turn_summoned; //Spell Buggy
/* 67 */ uint8 elemental_pact; //dont know
// ===== Necromancer =====
/* 68 */ uint8 life_burn; //works
/* 69 */ uint8 dead_mesmerization; //dont know
/* 70 */ uint8 fearstorm; //works
/* 71 */ uint8 flesh_to_bone; //not working
/* 72 */ uint8 call_to_corpse; //works but self only
// ===== Paladin =====
/* 73 */ uint8 divine_stun; //works
/* 74 */ uint8 improved_lay_of_hands; //dont know
/* 75 */ uint8 slay_undead; //dont know, 3 levs
/* 76 */ uint8 act_of_valor; //works
/* 77 */ uint8 holy_steed; //works but default fast horse
/* 78 */ uint8 fearless; //works
/* 79 */ uint8 two_hand_bash; //dont know
// ===== Ranger =====
/* 80 */ uint8 innate_camouflage; //works
/* 81 */ uint8 ambidexterity; //works
/* 82 */ uint8 archery_mastery; //works
/* 83 */ uint8 unknown83;
/* 84 */ uint8 endless_quiver; //works
// ===== Shadow Knight =====
/* 85 */ uint8 unholy_steed; //works but just a default fast horse~
/* 86 */ uint8 improved_harm_touch; //dont know, can fix
/* 87 */ uint8 leech_touch; //works
/* 88 */ uint8 unknown88;
/* 89 */ uint8 soul_abrasion; //works
// ===== Bard =====
/* 90 */ uint8 instrument_mastery; //dont know, 3 levs
/* 91 */ uint8 unknown91;
/* 92 */ uint8 unknown92;
/* 93 */ uint8 unknown93;
/* 94 */ uint8 jam_fest; //dont know, 3 levs
/* 95 */ uint8 unknown95;
/* 96 */ uint8 unknown96;
// ===== Monk =====
/* 97 */ uint8 critical_mend; //dont know, 3 levs
/* 98 */ uint8 purify_body; //dont know
/* 99 */ uint8 unknown99;
/* 100 */ uint8 rapid_feign; //dont know, 3 levs
/* 101 */ uint8 return_kick; //dont know, 3 levs
// ===== Rogue =====
/* 102 */ uint8 escape; //works
/* 103 */ uint8 poison_mastery; //dont know, 3 levs
/* 104 */ uint8 double_riposte; //dont know, 3 levs
/* 105 */ uint8 unknown105;
/* 106 */ uint8 unknown106;
/* 107 */ uint8 purge_poison; //works
// ===== Warrior =====
/* 108 */ uint8 flurry; //works
/* 109 */ uint8 rampage; //works
/* 110 */ uint8 area_taunt; //works
/* 111 */ uint8 warcry; //spell error
/* 112 */ uint8 bandage_wound; //dont know, 3 levs
// ===== (Other) =====
/* 113 */ uint8 spell_casting_reinforcement_mastery; //dont know
/* 114 */ uint8 spell_casting_fury_mastery; //works
/* 115 */ uint8 unknown115; //was extended notes
/* 116 */ uint8 dragon_punch; //dont know
/* 117 */ uint8 strong_root; //works
/* 118 */ uint8 singing_mastery; //dont know, 3 levs
/* 119 */ uint8 body_and_mind_rejuvenation; //not working
/* 120 */ uint8 physical_enhancement; //dont know
/* 121 */ uint8 adv_trap_negotiation; //dont know, 3 levs
/* 122 */ uint8 acrobatics; //dont know, 3 levs
/* 123 */ uint8 scribble_notes; //dont know
/* 124 */ uint8 chaotic_stab; //dont know
/* 125 */ uint8 pet_discipline; //not working
/* 126 */ uint8 hobble_of_spirits; //works
/* 127 */ uint8 frenzy_of_spirit; //works
/* 128 */ uint8 paragon_of_spirit; //works
} named;
} class_skills;
union {
uint8 unnamed[15];
struct {
/* 129 */ uint8 advanced_innate_strength; //works
/* 130 */ uint8 advanced_innate_stamina; //works
/* 131 */ uint8 advanced_innate_agility; //works
/* 132 */ uint8 advanced_innate_dexterity; //works
/* 133 */ uint8 advanced_innate_intelligence; //works
/* 134 */ uint8 advanced_innate_wisdom; //works
/* 135 */ uint8 advanced_innate_charisma; //works
/* 136 */ uint8 warding_of_solusek; //works
/* 137 */ uint8 blessing_of_eci; //works

/* 138 */ uint8 marrs_protection; //works
/* 139 */ uint8 shroud_of_the_faceless; //works
/* 140 */ uint8 bertoxxulous_gift; //works
/* 141 */ uint8 new_tanaan_crafting_mastery; //dont know
/* 142 */ uint8 planar_power; //works
/* 143 */ uint8 planar_durability; //works

} named;
} pop_advance;
union {
uint8 unnamed[77];
struct {
/* 144 */ uint8 innate_enlightenment; //works
/* 145 */ uint8 unknown145;
/* 146 */ uint8 advanced_healing_adept; //works
/* 147 */ uint8 advanced_healing_gift; //works
/* 148 */ uint8 coup_de_grace; //dont know, 3 levs
/* 149 */ uint8 fury_of_the_ages; //dont know, 3 levs
/* 150 */ uint8 mastery_of_the_past; //dont know, 3 levs
/* 151 */ uint8 lightning_reflexes; //dont know, 5 levs
/* 152 */ uint8 innate_defense; //dont know, 5 levs
/* 153 */ uint8 radiant_cure; //Works spell buggy
/* 154 */ uint8 hastened_divinity; //Works
/* 155 */ uint8 hastened_turning; //Works
/* 156 */ uint8 hastened_purification_of_the_soul; //Works
/* 157 */ uint8 hastened_gathering; //Works
/* 158 */ uint8 hastened_rabidity; //works
/* 159 */ uint8 hastened_exodus; //works
/* 160 */ uint8 hastened_root; //works
/* 161 */ uint8 hastened_mending; //Works
/* 162 */ uint8 hastened_banishment; //Works
/* 163 */ uint8 hastened_instigation; //Works
/* 164 */ uint8 furious_rampage; //Works

/* 165 */ uint8 hastened_purification_of_the_body; //works
/* 166 */ uint8 hasty_exit; //works
/* 167 */ uint8 hastened_purification; //works
/* 168 */ uint8 flash_of_steel; //dont know, 3 levs, addon buff
/* 169 */ uint8 divine_arbitration; //spell error
/* 170 */ uint8 wrath_of_the_wild; //works
/* 171 */ uint8 virulent_paralysis; //works
/* 172 */ uint8 harvest_of_druzzil; //works
/* 173 */ uint8 eldritch_rune; //Works
/* 174 */ uint8 servant_of_ro; //works
/* 175 */ uint8 wake_the_dead; //works
/* 176 */ uint8 suspended_minion; //Spell errors
/* 177 */ uint8 spirit_call; //works
/* 178 */ uint8 celestial_renewal; //Works
/* 179 */ uint8 allegiant_familiar; //works
/* 180 */ uint8 hand_of_piety; //works

/* 181 */ uint8 mithaniels_binding; //dont know, 2 levs
/* 182 */ uint8 mending_of_the_tranquil; //dont know, 3 levs
/* 183 */ uint8 raging_flurry; //dont know, 3 levs, addon buff
/* 184 */ uint8 guardian_of_the_forest; //works
/* 185 */ uint8 spirit_of_the_wood; //works
/* 186 */ uint8 bestial_frenzy; //dont know, 5 levs
/* 187 */ uint8 harmonious_attack; //dont know, 5 levs
/* 188 */ uint8 knights_advantage; //dont know, 3 levs
/* 189 */ uint8 ferocity; //dont know, 3 levs
/* 190 */ uint8 viscid_roots; //dont know
/* 191 */ uint8 unknown191;
/* 192 */ uint8 ayonaes_tutelage; //dont know, 3 levs
/* 193 */ uint8 feigned_minion; //dont know, 3 levs
/* 194 */ uint8 unfailing_divinity; //dont know, 3 levs
/* 195 */ uint8 animation_empathy; //dont know, 3 levs
/* 196 */ uint8 rush_to_judgment; //works

/* 197 */ uint8 living_shield; //dont know, 3 levs, disc reuse buff
/* 198 */ uint8 consumption_of_the_soul; //dont know, 3 levs, addon
/* 199 */ uint8 boastful_bellow; //works
/* 200 */ uint8 fervent_blessing; //dont know, 3 levs, reuse skill 12 minutes each
/* 201 */ uint8 touch_of_the_wicked; //dont know, 3 levs, reuse buff 12 minutes each
/* 202 */ uint8 punishing_blade; //dont know, 3 levs
/* 203 */ uint8 speed_of_the_knight; //dont know, 3 levs
/* 204 */ uint8 shround_of_stealth; //dont know
/* 205 */ uint8 nimble_evasion; //dont know, 5 levs
/* 206 */ uint8 technique_of_master_wu; //dont know, 5 levs
/* 207 */ uint8 host_of_the_elements; //works
/* 208 */ uint8 call_of_xuzl; //works
/* 209 */ uint8 hastened_stealth; //works
/* 210 */ uint8 ingenuity; //dont know, 3 levs
/* 211 */ uint8 fleet_of_foot; //dont know, 2 levs
/* 212 */ uint8 fading_memories; //works


/* 213 */ uint8 tactical_mastery; //dont know, 3 levs
/* 214 */ uint8 theft_of_life; //works
/* 215 */ uint8 fury_of_magic; //works cleric
/* 216 */ uint8 fury_of_magic_mastery; //works
/* 217 */ uint8 project_illusion; //spell error
/* 218 */ uint8 headshot; //works
/* 219 */ uint8 entrap; //works
/* 220 */ uint8 unholy_touch; //dont know, 3 levs, addon
} named;
} pop_ability;
union {
uint8 unnamed[89];
struct {
/* 221 */ uint8 total_domination; //dont know, 3 levs
/* 222 */ uint8 stalwart_endurance; //dont know, 3 levs
/* 223 */ uint8 quick_summoning; //dont know, 3 levs
/* 224 */ uint8 mental_clarity; //not working, 3 levs
/* 225 */ uint8 innate_regeneration; //works
/* 226 */ uint8 mana_burn; //works
/* 227 */ uint8 extended_notes; //dont know, 3 levs
/* 228 */ uint8 sionachies_crescendo; //dont know, 3 levs
/* 229 */ uint8 improved_reclaim_energy; //dont know

/* 230 */ uint8 swift_journey; //dont know, 2 levs
/* 231 */ uint8 convalescence; //dont know, 2 levs
/* 232 */ uint8 lasting_breath; //dont know, 2 levs
/* 233 */ uint8 packrat; //dont know
/* 234 */ uint8 heightened_endurance; //dont know, 3 levs
/* 235 */ uint8 weapon_affinity; //dont know, 5 levs
/* 236 */ uint8 secondary_forte; //dont know
/* 237 */ uint8 persistent_casting; //dont know, 3 levs
/* 238 */ uint8 tune_of_pursuance; //dont know, 5 levs
/* 239 */ uint8 improved_instrument_mastery; //dont know

/* 240 */ uint8 improved_singing_mastery; //dont know
/* 241 */ uint8 exultant_bellowing; //dont know, 5 levs
/* 242 */ uint8 echo_of_taelosia; //dont know, 3 levs
/* 243 */ uint8 internal_metronome; //dont know, 5 levs
/* 244 */ uint8 pious_supplication; //dont know, 3 levs, addon
/* 245 */ uint8 bestial_alignment; //dont know, 3 levs, spell error
/* 246 */ uint8 wrath_of_xuzl; //works need to add button
/* 247 */ uint8 feral_swipe; //spell error
/* 248 */ uint8 warders_fury; //dont know, 5 levs
/* 249 */ uint8 warders_alacrity; //dont know, 5 levs

/* 250 */ uint8 pet_affinity; //dont know
/* 251 */ uint8 mastery_of_the_past; //dont know, 3 levs, beastlord only?
/* 252 */ uint8 spell_casting_subtlety; //dont know, 3 levs
/* 253 */ uint8 touch_of_the_divine; //dont know, 5 levs
/* 254 */ uint8 divine_avatar; //need to implement
/* 255 */ uint8 exquisite_benediction; //need to implement
/* 256 */ uint8 quickened_curing; //Works
/* 257 */ uint8 natures_boon; //need to implement
/* 258 */ uint8 advanced_tracking; //dont know, 5 levs
/* 259 */ uint8 critical_affliction; //dont know, 3 levs

/* 260 */ uint8 fury_of_magic_mastery; //works
/* 261 */ uint8 doppelganger; //works- lil off
/* 262 */ uint8 enhanced_forgetfulness; //dont know, 5 levs
/* 263 */ uint8 mesmerization_mastery; //dont know
/* 264 */ uint8 quick_mass_group_buff; //Works
/* 265 */ uint8 shared_health; //Not Working
/* 266 */ uint8 elemental_fury; //dont know, 5 levs
/* 267 */ uint8 elemental_alacrity; //dont know, 5 levs
/* 268 */ uint8 elemental_agility; //dont know, 3 levs
/* 269 */ uint8 elemental_durability; //dont know, 3 levs

/* 270 */ uint8 sinister_strikes; //dont know, addon
/* 271 */ uint8 strikethrough; //dont know, 3 levs
/* 272 */ uint8 stonewall; //dont know, 5 levs
/* 273 */ uint8 rapid_strikes; //dont know, 5 levs
/* 274 */ uint8 kick_mastery; //dont know, 3 levs
/* 275 */ uint8 heightened_awareness; //dont know, 5 levs
/* 276 */ uint8 destructive_force; //dont know, 3 levs
/* 277 */ uint8 swarm_of_decay; //works- lil off
/* 278 */ uint8 deaths_fury; //dont know, 5 levs
/* 279 */ uint8 quickening_of_death; //dont know, 5 levs

/* 280 */ uint8 advanced_theft_of_life; //need to implement, 2 levs
/* 281 */ uint8 triple_backstab; //dont know, 3 levs
/* 282 */ uint8 hastened_piety; //works
/* 283 */ uint8 immobilizing_bash; //dont know, 3 levs
/* 284 */ uint8 vicious_smash; //dont know, 5 levs
/* 285 */ uint8 radiant_cure; //spell errors
/* 286 */ uint8 purification; //spell error
/* 287 */ uint8 precision_of_the_pathfinder; //dont know, 3 levs
/* 288 */ uint8 coat_of_thistles; //dont know, 5 levs
/* 289 */ uint8 flaming_arrows; //not working

/* 290 */ uint8 frost_arrows; //not working
/* 291 */ uint8 seized_opportunity; //dont know, 3 levs
/* 292 */ uint8 trap_circumvention; //dont know, 5 levs
/* 293 */ uint8 improved_hasty_exit; //works
/* 294 */ uint8 virulent_venom; //dont know, 5 levs
/* 295 */ uint8 improved_consumption_of_the_soul; //dont know, 2 levs, addon
/* 296 */ uint8 intense_hatred; //dont know, 5 levs
/* 297 */ uint8 advanced_spirit_call; //works needs button
/* 298 */ uint8 call_of_the_ancients; //needs implemented
/* 299 */ uint8 sturdiness; //dont know, 5 levs

/* 300 */ uint8 warlords_tenacity; //works
/* 301 */ uint8 strengthened_strike; //dont know, 3 levs
/* 302 */ uint8 extended_shielding; //dont know, 3 levs
/* 303 */ uint8 ros_flaming_familiar; //spell error
/* 304 */ uint8 ecis_icy_familiar; //spell error
/* 305 */ uint8 druzzils_mystical_familiar; //spell error
/* 306 */ uint8 advanced_fury_of_magic_mastery;//works
/* 307 */ uint8 ward_of_destruction; //needs implemented
/* 308 */ uint8 frenzied_devastation; //not working 3 levs, spell error
/* 309 */ uint8 unknown309;
} named;
} god_ability;
};


zone\client.cpp around line 3264
replace exsisintg with-


void Client::ActivateAA(int activate){
int32 timermod=0;
Mob *target=CastToClient()->GetTarget();
Mob *c=CastToClient();
int ct=CastToClient()->GetID();
int targ;
switch(activate){
case 35: //MGB---AE cast group spell in slot 1
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.mass_group_buff;
if(cur_level == 1)
{
CastToClient()->Message(0,"Casting Spell in Slot 1 as an Area Effect");
int spell=m_pp.mem_spells[0];
if((IsGroupSpell(spell))&&(!IsEffectInSpell(spell, SE_Gate))&&
(!IsEffectInSpell(spell, SE_Translocate))&&(!IsEffectInSpell(spell, SE_Teleport))
&&(!IsEffectInSpell(spell, SE_Succor)))
{
int mana;
mana = spells[spell].mana;
mana = (GetActSpellCost(spell, mana))*2;
if(c->GetMana() >= mana)
{
int newmana=(c->GetMana() - mana);
entity_list.AESpell(c,c,100,spell);
c->CastSpell(spell,ct,9,0,0,0,0);
c->SetMana(newmana);
}
else
{
c->Message(13,"Insufficient Mana to cast this Spell.");
break;
}
}
else
{
c->Message(0,"MGB only works with Group Buffs!");
break;
}
int usemod=CastToClient()->GetAAStruct()->god_ability.named.quick_mass_group_buff;
int time;
if(usemod == 1){time=3888;}
else if(usemod == 2){time=3456;}
else if(usemod == 3){time=3024;}
else{time=4320;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 36: //divine rezz
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.divine_resurrection;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2738,targ,9,0,0,0,0);
timermod=64800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 37: //innate ivu
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.innate_invis_to_undead;
if(cur_level == 1)
{
CastSpell(2739,targ,9,0,0,0,0);
timermod=7;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 38: //celest regen
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.celestial_regeneration;
if(cur_level == 1)
{
int mod=CastToClient()->GetAAStruct()->pop_ability.named.celestial_renewal;
int spell;
if(mod == 0){spell=2740;}
else if(mod==1){spell=3250;}
else if(mod==2){spell=3251;}
CastSpell(spell,targ,9,100,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"you have not learned this skill");
}
break;
case 39: //bestow DA
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.bestow_divine_aura;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2741,targ,9,0,0,0,0);
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_divinity;
int time;
if(mod == 0){time=8640;}
else if(mod == 1){time=7776;}
else if(mod == 2){time=6912;}
else if(mod == 3){time=6048;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 40: //turn undead
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.turn_undead;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_turning;
if(cur_level > 0)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=2776;}
else if(cur_level==2){spell=2777;}
else if(cur_level==3){spell=2778;}
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
CastSpell(spell,targ,9,2500,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 41: //purify soul
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.purify_soul;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_purification_of_the_sou l;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2742,targ,9,0,0,0,0);
int time;
if(mod==0){time=1800;}
else if(mod==1){time=1620;}
else if(mod==2){time=1440;}
else if(mod==3){time=1260;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 43: //exodus
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.exodus;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_exodus;
if(cur_level==1)
{
CastSpell(2771,targ,9,100,0,0,0);
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 46: //dire charm
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.dire_charm;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if((CastToClient()->GetClass())==DRUID){spell=2760;}
else if((CastToClient()->GetClass())==ENCHANTER){spell=2761;}
else if((CastToClient()->GetClass())==NECROMANCER){spell=2759;}
CastSpell(spell,targ,9,6000,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 47: //cannibalization
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.cannibalization;
if(cur_level == 1)
{
CastSpell(2749,targ,9,2500,0,0,0);
timermod=180;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 50: //rabid bear
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.rabid_bear;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_rabidity;
if(cur_level==1)
{
int time;
if(mod==0){time=7200;}
else if(mod==1){time=6480;}
else if(mod==2){time=5760;}
else if(mod==3){time=5040;}
CastSpell(2750,targ,9,100,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 52: //wizard familiars
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.improved_familiar;
if(cur_level==1)
{
int mod=CastToClient()->GetAAStruct()->pop_ability.named.allegiant_familiar;
int spell;
if(mod==0){spell=2758;}
else if(mod==1){spell=3264;}
CastSpell(spell,targ,9,16000,0,0,0);
timermod=7;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 53: //nexus gate
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.nexus_gate;
if(cur_level==1)
{
CastSpell(2734,targ,9,0,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 57: //gather mana
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.gather_mana;
if(cur_level==1)
{
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_gathering;
int time;
if(mod==0){time=8640;}
else if(mod==1){time=7776;}
else if(mod==2){time=6912;}
else if(mod==3){time=6048;}
CastSpell(2753,targ,9,2000,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 58: //Mend Companion
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.mend_companion;
if(cur_level==1)
{
targ=ct;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_mending;
int time;
if(mod==0){time=2160;}
else if(mod==1){time=1944;}
else if(mod==2){time=1728;}
else if(mod==3){time=1512;}
CastSpell(2752,targ,9,0,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 60: //Frenzied Burnout
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.frenzied_burnout;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2754,targ,9,2000,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 61: //mage ele form fire
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.elemental_form_fire;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=2795;}
if(cur_level==2){spell=2796;}
if(cur_level==3){spell=2797;}
CastSpell(spell,targ,9,8000,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 62: //mage ele form water
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.elemental_form_water;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=2798;}
if(cur_level==2){spell=2799;}
if(cur_level==3){spell=2800;}
CastSpell(spell,targ,9,8000,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 63: //mage ele form earth
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.elemental_form_earth;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=2792;}
if(cur_level==2){spell=2793;}
if(cur_level==3){spell=2794;}
CastSpell(spell,targ,9,8000,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 64: //mage ele form air
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.elemental_form_air;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=2789;}
if(cur_level==2){spell=2790;}
if(cur_level==3){spell=2791;}
CastSpell(spell,targ,9,8000,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 66: //turn summoned.....supposed to be 3 levs?? UI only has 1??
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.turn_summoned;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_banishment;
if(cur_level > 0)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=2779;}
else if(cur_level==2){spell=2780;}
else if(cur_level==3){spell=2781;}
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
CastSpell(spell,targ,9,2500,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 68: //Life Burn
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.life_burn;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2755,targ,9,6000,0,0,0);
timermod=8640;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 69: //Dead mesmerization
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.dead_mesmerization;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Dead Mesmerization not working YET");
CastSpell(2756,targ,9,3000,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 70: //fearstorm
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.fearstorm;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2757,targ,9,3000,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 71: //flesh to bone
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.flesh_to_bone;
if(cur_level==1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Flesh to Bone not working YET");
CastSpell(2772,targ,9,3000,0,0,0);
timermod=7;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 72: //call to corpse
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.call_to_corpse;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2764,targ,9,5000,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 73: //divine stun
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.divine_stun;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.rush_to_judgment;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int time;
if(mod==0){time=30;}
else if(mod==1){time=23;}
else if(mod==2){time=16;}
else if(mod==3){time=9;}
CastSpell(2190,targ,9,1500,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 76: //act of valor
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.act_of_valor;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2775,targ,9,0,0,0,0);
int heal=c->GetHP();
int curhp=target->GetHP();
target->SetHP(heal+curhp);
c->Death(c,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 77: //holy steed------Default fast horse
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.holy_steed;
if(cur_level == 1)
{
targ=ct;
CastSpell(2871,targ,9,2000,0,0,0);
timermod=1;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 80: //innate camo
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.innate_camouflage;
if(cur_level == 1)
{
targ=ct;
CastSpell(2765,targ,9,1,0,0,0);
timermod=7;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 85: //unholy steed-----default fast horse
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.unholy_steed;
if(cur_level == 1)
{
targ=ct;
CastSpell(2918,targ,9,2000,0,0,0);
timermod=1;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 86: //Improved HT
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.improved_harm_touch;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry Improved harmtouch not working YET");
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 87: //Leech touch
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.leech_touch;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2766,targ,9,1,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 98: //purify body
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.purify_body;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_purification_of_the_bod y;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Purify Body not working YET");
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
CastSpell(2190,targ,9,0,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 102: //escape
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.escape;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hasty_exit;
int modtwo=CastToClient()->GetAAStruct()->god_ability.named.improved_hasty_exit;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Escape not working YET");
int time;
if(mod==0){time=4320;}
else if((mod==1)&&(modtwo==0)){time=3888;}
else if((mod==2)&&(modtwo==0)){time=3456;}
else if((mod==3)&&(modtwo==0)){time=3024;}
else if((mod==3)&&(modtwo==1)){time=2592;}
else if((mod==3)&&(modtwo==2)){time=2175;}
CastSpell(5244,targ,9,0,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 107: //purge poison
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.purge_poison;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_purification;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Purify Body not working YET");
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
CastSpell(5232,targ,9,0,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 109: //rampage
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.rampage;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.furious_rampage;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
Attack(target,13);
int time;
if(mod==0){time=600;}
else if(mod==1){time=540;}
else if(mod==2){time=480;}
else if(mod==3){time=420;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 110: //AE taunt
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.area_taunt;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_instigation;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, AE Taunt not working YET");
int time;
if(mod==0){time=900;}
else if(mod==1){time=810;}
else if(mod==2){time=720;}
else if(mod==3){time=630;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 111: //warcry
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.warcry;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Warcry not working YET");
int spell;
if(cur_level==1){spell=5229;}
else if(cur_level==2){spell=5230;}
else if(cur_level==3){spell=5231;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=2160;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 117: //strong root
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.strong_root;
int mod=CastToClient()->GetAAStruct()->pop_ability.named.hastened_root;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int time;
if(mod==0){time=4320;}
else if(mod==1){time=3888;}
else if(mod==2){time=3456;}
else if(mod==3){time=3024;}
CastSpell(2748,targ,9,2000,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 126: //hobble of spirits
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.hobble_of_spirits;
if(cur_level == 1)
{
targ=ct;
CastSpell(3290,targ,9,3000,0,0,0);
timermod=300;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 127: //frenzy of spirit
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.frenzy_of_spirit;
if(cur_level == 1)
{
targ=ct;
CastSpell(3289,targ,9,0,0,0,0);
timermod=720;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 128: //paragon
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.paragon_of_spirit;
if(cur_level == 1)
{
targ=ct;
CastSpell(3291,targ,9,5000,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 153: //radiant cure
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.radiant_cure;
int mod=CastToClient()->GetAAStruct()->god_ability.named.quickened_curing;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3297;}
else if(cur_level==2){spell=3298;}
else if(cur_level==3){spell=3299;}
int time;
if(mod==0){time=180;}
else if(mod==1){time=162;}
else if(mod==2){time=144;}
else if(mod==3){time=126;}
CastSpell(spell,targ,9,3500,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 169: //divine arbitration
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.divine_arbitration;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3252;}
else if(cur_level==2){spell=3253;}
else if(cur_level==3){spell=3254;}
CastSpell(spell,targ,9,750,0,0,0);
timermod=180;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 170: //wrath of the wild
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.wrath_of_the_wild;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=3255;}
else if(cur_level==2){spell=3256;}
else if(cur_level==3){spell=3257;}
CastSpell(spell,targ,9,1000,0,0,0);
timermod=240;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 171: //virulent paralysis
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.virulent_paralysis;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=3274;}
else if(cur_level==2){spell=3275;}
else if(cur_level==3){spell=3276;}
CastSpell(spell,targ,9,2000,0,0,0);
timermod=120;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 172: //harvest of druzzil
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.harvest_of_druzzil;
if(cur_level == 1)
{
targ=ct;
CastSpell(3338,targ,9,10000,0,0,0);
timermod=480;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 173: //eldritch rune
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.eldritch_rune;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3258;}
else if(cur_level==2){spell=3259;}
else if(cur_level==3){spell=3260;}
CastSpell(spell,targ,9,1,0,0,0);
timermod=600;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 174: //servant of ro
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.servant_of_ro;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Servant of Ro not working YET");
int spell;
if(cur_level==1){spell=3265;}
else if(cur_level==2){spell=3266;}
else if(cur_level==3){spell=3267;}
CastSpell(spell,targ,9,500,0,0,0);
timermod=540;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 175: //wake the dead
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.wake_the_dead;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Wake the Dead not working YET");
int spell;
if(cur_level==1){spell=3268;}
else if(cur_level==2){spell=3269;}
else if(cur_level==3){spell=3270;}
CastSpell(spell,targ,9,8000,0,0,0);
timermod=540;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 176: //suspend minion
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.suspended_minion;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry Suspend Minion not working YET");
int spell;
if(cur_level==1){spell=3248;}
else if(cur_level==2){spell=3249;}
CastSpell(spell,targ,9,4000,0,0,0);
timermod=1;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 177: //spirit call
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.spirit_call;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Spirit Call not working YET");
int spell;
if(cur_level==1){spell=3283;}
else if(cur_level==2){spell=3284;}
else if(cur_level==3){spell=3285;}
CastSpell(spell,targ,9,6500,0,0,0);
timermod=720;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 180: //hand of piety
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.hand_of_piety;
int mod=CastToClient()->GetAAStruct()->god_ability.named.hastened_piety;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3261;}
else if(cur_level==2){spell=3262;}
else if(cur_level==3){spell=3263;}
int time;
if(mod==0){time=2160;}
else if(mod==1){time=1920;}
else if(mod==2){time=1680;}
else if(mod==3){time=1440;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 184: //guardian of the forest
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.guardian_of_the_forest;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3271;}
else if(cur_level==2){spell=3272;}
else if(cur_level==3){spell=3273;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 185: //spirit of the wood
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.spirit_of_the_wood;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3277;}
else if(cur_level==2){spell=3278;}
else if(cur_level==3){spell=3279;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 199: //boastfull bellow
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.boastful_bellow;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(3282,targ,9,0,0,0,0);
timermod=18;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 207: //host of elements
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.host_of_the_elements;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=3286;}
else if(cur_level==2){spell=3287;}
else if(cur_level==3){spell=3288;}
CastSpell(spell,targ,9,6500,0,0,0);
timermod=1320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 208: //call of xuzl
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.call_of_xuzl;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
if(cur_level==1){spell=3292;}
else if(cur_level==2){spell=3293;}
else if(cur_level==3){spell=3294;}
CastSpell(spell,targ,9,6500,0,0,0);
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;

Branks
08-01-2004, 02:46 PM
uhh whoops seems there some limit as to how much one post can display so heres the rest of the stuff from case 212 down




case 212: //fading memories
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.fading_memories;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry Fading Memories not working YET");
CastSpell(5243,targ,9,0,0,0,0);
timermod=1;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 217: //project illusion
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.project_illusion;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Project Illusion not working YET");
timermod=1;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 219: //entrap
{
int cur_level=CastToClient()->GetAAStruct()->pop_ability.named.entrap;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(3614,targ,9,1750,0,0,0);
timermod=5;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 226: //manaburn
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.mana_burn;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2751,targ,9,6000,0,0,0);
timermod=8640;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 245: //bestial allignment
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.bestial_alignment;
if(cur_level >= 1)
{
CastToClient()->Message(0,"Sorry Bestial Alignment not working YET");
targ=ct;
int crace=CastToClient()->GetBaseRace();
int spell;
if((cur_level==1)&&(crace==2)){spell=4521;}
else if((cur_level==2)&&(crace==2)){spell=4522;}
else if((cur_level==3)&&(crace==2)){spell=4523;}
else if((cur_level==1)&&(crace==9)){spell=4524;}
else if((cur_level==2)&&(crace==9)){spell=4525;}
else if((cur_level==3)&&(crace==9)){spell=4526;}
else if((cur_level==1)&&(crace==10)){spell=4527;}
else if((cur_level==2)&&(crace==10)){spell=4528;}
else if((cur_level==3)&&(crace==10)){spell=4529;}
else if((cur_level==1)&&(crace==128)){spell=4530;}
else if((cur_level==2)&&(crace==128)){spell=4531;}
else if((cur_level==3)&&(crace==128)){spell=4532;}
else if((cur_level==1)&&(crace==130)){spell=4533;}
else if((cur_level==2)&&(crace==130)){spell=4534;}
else if((cur_level==3)&&(crace==130)){spell=4535;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 247: //feral swipe
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.feral_swipe;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastToClient()->Message(0,"Sorry, Feral Swipe not working YET");
CastSpell(4788,targ,9,0,0,0,0);
timermod=60;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 254: //divine avatar
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.divine_avatar;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry, Divine Avatar not working YET");
if(cur_level==1){spell=4549;}
else if(cur_level==2){spell=4550;}
else if(cur_level==3){spell=4551;}
CastSpell(spell,targ,9,3000,0,0,0);
timermod=7200;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 255: //equisite benadiction
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.exquisite_benediction;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry Equisite Benediction not working YET");
if(cur_level==1){spell=4790;}
else if(cur_level==2){spell=4791;}
else if(cur_level==3){spell=4792;}
else if(cur_level==4){spell=4793;}
else if(cur_level==5){spell=4794;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 257: //natures boon
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.natures_boon;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry Natures Boon not working YET");
if(cur_level==1){spell=4796;}
else if(cur_level==2){spell=4797;}
else if(cur_level==3){spell=4798;}
else if(cur_level==4){spell=4799;}
else if(cur_level==5){spell=4800;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 261: //doppelganger
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.doppelganger;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry Doppelganer not working YET");
if(cur_level==1){spell=4552;}
else if(cur_level==2){spell=4553;}
else if(cur_level==3){spell=4554;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 265: //shared health
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.shared_health;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Shared Health not working YET");
timermod=900;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 276: //destructive force 3 levs
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.destructive_force;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Destructive Force not working YET");
timermod=3600;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 277: //swarm of decay
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.swarm_of_decay;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
CastToClient()->Message(0,"Sorry Swarm of Decay not working YET");
if(cur_level==1){spell=4564;}
else if(cur_level==2){spell=4565;}
else if(cur_level==3){spell=4566;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 285: //radiant cure 2?????
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.radiant_cure;
int mod=CastToClient()->GetAAStruct()->god_ability.named.quickened_curing;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=3297;}
else if(cur_level==2){spell=3298;}
else if(cur_level==3){spell=3299;}
int time;
if(mod==0){time=180;}
else if(mod==1){time=162;}
else if(mod==2){time=144;}
else if(mod==3){time=126;}
CastSpell(spell,targ,9,3500,0,0,0);
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 286: //purification---made it a self only purify soul
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.purification;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry, Purification not working, enjoy your self only purify soul");
CastSpell(2742,targ,9,0,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 289: //flaming arrows
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.flaming_arrows;;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Flaming Arrows not working YET");
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 290: //frost arrows
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.frost_arrows;;
if(cur_level >= 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Frost Arrows not working YET");
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 298: //call of the ancients
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.call_of_the_ancients;
if(cur_level >= 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
int spell;
CastToClient()->Message(0,"Sorry Call of the Ancients not working YET");
if(cur_level==1){spell=4828;}
else if(cur_level==2){spell=4829;}
else if(cur_level==3){spell=4830;}
else if(cur_level==4){spell=4831;}
else if(cur_level==5){spell=4832;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 300: //warlords tenacity
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.warlords_tenacity;
if(cur_level >= 1)
{
targ=ct;
int spell;
if(cur_level==1){spell=4925;}
else if(cur_level==2){spell=4926;}
else if(cur_level==3){spell=4927;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=3600;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 303: //ro's flaming familiar
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.ros_flaming_familiar;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Ro's Flaming Familiar not working YET");
CastSpell(4833,targ,9,0,0,0,0);
timermod=60;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 304: //eci's icy familiar
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.ecis_icy_familiar;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Eci's Icy Familiar not working YET");
CastSpell(4834,targ,9,0,0,0,0);
timermod=60;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 305: //druzzils familiar
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.druzzils_mystical_familiar;
if(cur_level == 1)
{
targ=ct;
CastToClient()->Message(0,"Sorry Druzzil's Mystical Familiar not working YET");
CastSpell(4835,targ,9,0,0,0,0);
timermod=60;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 307: //ward of destruction
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.call_of_the_ancients;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry Ward of Destruction not working YET");
if(cur_level==1){spell=4836;}
else if(cur_level==2){spell=4837;}
else if(cur_level==3){spell=4838;}
else if(cur_level==4){spell=4839;}
else if(cur_level==5){spell=4840;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=1800;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;
case 308: //frenzied devastation
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.frenzied_devastation;
if(cur_level >= 1)
{
targ=ct;
int spell;
CastToClient()->Message(0,"Sorry Frenzied Devastation not working YET");
if(cur_level==1){spell=5245;}
else if(cur_level==2){spell=5246;}
else if(cur_level==3){spell=5247;}
CastSpell(spell,targ,9,0,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;

}
time_t timestamp=time(NULL);

APPLAYER* outapp = new APPLAYER(OP_AAAction,sizeof(UseAA_Struct));
UseAA_Struct* uaa = (UseAA_Struct*)outapp->pBuffer;
uaa->ability=activate;
uaa->begin=timestamp;
uaa->end=timestamp;
database.UpdateAATimers(this->CharacterID(),timestamp+timermod,timestamp,activat e);
AbilityTimer=true;
QueuePacket(outapp);
safe_delete(outapp);
}



anyway um i think i did that correctly if not ill try to fix it, sorry ive never done this before, also let me state again im just learning so please feel free to explain how i maybe did something wrong or suggestions on how to make this better, also does anyone know how to make an if statement for things such as manaburn were it would need values not included in the spell? ive tried thigns like
if(SpellFinished == TRUE) and the result is always that the damage happens the instant the button is pushed, anyone know of a way to make it interuptable and wait untill casting is complete? anyway questions, comments, suggestons appreciated.

Branks
08-01-2004, 04:50 PM
also a shadowknight friend of mine told me that after level 40 HT is a different spell so i tried correcting it in zone/client_process.cpp around line 2127 by adding


else if((GetClass() == SHADOWKNIGHT)&&(GetLevel() <= 39))
{
ability=89; // solar: TODO check this value, why is it not 88?
spell_to_cast = 88;
}
else if((GetClass() == SHADOWKNIGHT)&&(GetLevel() >= 40))
{
ability=89;
spell_to_cast = 2821;
}
else



however the line below it



if(spell_to_cast != castspell->spell_id)
{
InterruptSpell(castspell->spell_id); //CHEATER!!!
break;
}




prevents spell 2821 from being cast, so does anyone know how i could make 2821 an allowable spell for HT since im pretty sure it is correct, but i may be wrong since ive never played an SK myself.

also as a correction to the above post in case 117 in client.cpp strong root, the cast time should be 2 seconds correct this by making line 4052- CastSpell(2748,targ,9,2000,0,0,0); anyway uh thanks again.

Branks
08-03-2004, 11:46 AM
So im the only one working on fixing AA or interested in them i guess? well anyway they'll be here if anyone else ever is /shrug.

Heres the fix for a 100% working manaburn, well except for the reuse timer which ill fix shortly i guess, NOTE you must edit the spell in spells_us.txt or spells_en.txt to make the damage 0.

ok in zone\spells.cpp around line 879 add the following-

updated in later post.



then in zone\client.cpp correct case 226 to be-


case 226: //manaburn
{
int cur_level=CastToClient()->GetAAStruct()->god_ability.named.mana_burn;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2751,targ,9,6000,0,0,0);
timermod=8640;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;


i know lifeburn is very similar so i should have it fixed within a few minutes, please tell me someone has atleast tested these out?
also should i repost the above code from my first post since i messed it up a little, so its more copy and paste friendly? also does anyone know the itemslot number for the item on the cursor? or have any other ideas as to how to make flesh to bone work?
anyway thanks again.

Scorpious2k
08-03-2004, 02:05 PM
Sometimes it takes a while for something to soak in.

Give them time to figure out what you did.

And good job!

Branks
08-03-2004, 03:14 PM
thanks scorpious2k, im really hoping those who have servers of their own and maybe a little freetime will throw this in and test a few out, as i wont even claim to know how most of them actually work so i just put in the default cast time etc etc while the actual skill may be instant, also to test if there are other side effects other than zone.exe finding any invalid AA profile the first 2 or 3 times an exsisting character with AA zones. useing a BACKUP database of course!

anyway here lifeburn as i think it should be going by the description in EQ~
zone\spells.cpp around line 896 assuming you already put manaburn in here-

updated in later post.


dont forget to edit the servers spell listing for lifeburn in spell_us.txt or spells_en.txt also so that lifeburn does 0 damage.

zone\client.cpp case 68


case 68: //Life Burn
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.life_burn;
if(cur_level==1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2755,targ,9,6000,0,0,0);
timermod=8640;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;


anyway since ive only played a warrior and wizard im unsure of how this is supposed to work but this makes the spell cast 6 seconds does damage = to your current hp, then sets your current hp to 1 and does the lifebond effect for 250 a tick, this correct?

Draupner
08-03-2004, 03:28 PM
lifeburn does your damage in hp lowers you to 25% hp and then gives you a 250 hp a tick regen for 4 ticks

Branks
08-11-2004, 03:34 PM
still working on this but been busy, anyway heres a few others that might be good enough to use.

lifeburn correction, although the FD effect in the recource is real buggy and causes the spell to be no agro, suppose to?
zone\spells.cpp repleace exsisting with-

updated in later post.


Fearless and Fear resistance, also in zone\spells.cpp around line 1708 add-


// solar: now check if the spell is allowed to land

if((spelltar->IsClient())&&(IsEffectInSpell(spell_id,SE_Fear))&& ((spelltar->CastToClient()->GetAAStruct()->class_skills.named.fearless)==1))
{
entity_list.MessageClose(spelltar, false, 50, 0, "%s has no Fear!", spelltar->GetName());
return false;
}
if((spelltar->IsClient())&&(IsEffectInSpell(spell_id,SE_Fear))&& ((spelltar->CastToClient()->GetAAStruct()->archetype_skills.named.fear_resistance)>=1))
{
int lev=spelltar->CastToClient()->GetAAStruct()->archetype_skills.named.fear_resistance;
int r=MakeRandomInt(1,100);
if((lev == 1)&&(r >= 95))
{
spelltar->CastToClient()->Message(0,"You overcome your Fears.");
return false;
}
else if((lev == 2)&&(r >= 90))
{
spelltar->CastToClient()->Message(0,"You overcome your Fears.");
return false;
}
else if((lev == 3)&&(r >= 75))
{
spelltar->CastToClient()->Message(0,"You overcome your Fears.");
return false;
}
}


act of valor- zone/client.cpp around line 3808 replace exsisting with-

case 76: //act of valor
{
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.act_of_valor;
if(cur_level == 1)
{
if(target>0){targ=target->GetID();}
else if(target==0)
{
CastToClient()->Message(0,"Skill requires a target");
break;
}
CastSpell(2775,targ,9,0,0,0,0);
int heal=c->GetHP();
int curhp=target->GetHP();
target->SetHP(heal+curhp);
c->Death(c,0,0,0);
timermod=4320;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;


also in client.cpp around line 4308 change case 186 to 184 to correct guardian of the forrest.

Archery Mastery and headshot i went through some logs of ranger friends from live and found a lot of the current archery code to be incorrect IMO so i kinda redid a whole lot of it and added a level check that brings things much closer to live i believe, i think its better but far from perfect yet, anyway
zone/client_process.cpp around line 2268- remove everything from
float chancetohit = 0;
down to the } that is right above
float multiple=(GetLevel()/5);
and replace with-


float chancetohit = 0;
if(target){
if(target->IsNPC())
chancetohit = GetSkill(ARCHERY) / 3.75;
else
chancetohit = GetSkill(ARCHERY) / 4.75; //harder to hit players

if (m_pp.level-target->GetLevel() < 0) {
chancetohit -= (float)((target->GetLevel()-m_pp.level)*(target->GetLevel()-m_pp.level))/4;
}

int16 targetagi = target->GetAGI();
int16 playerDex = (int16)(this->itembonuses->DEX + this->spellbonuses->DEX)/2;
int16 levmod =0;
if((this->GetLevel()-20) <= (target->GetLevel()))
{
levmod = ((target->GetLevel())-(this->GetLevel()-20))*0.5;
}

targetagi = (targetagi <= 200) ? targetagi:targetagi + ((targetagi-200)/5);
chancetohit -= (float)targetagi*0.05;
chancetohit += playerDex;
chancetohit = (chancetohit > 0) ? chancetohit+30:30;
chancetohit -= levmod;
chancetohit = chancetohit*0.5;
chancetohit = chancetohit > 95 ? 95 : chancetohit; // cap to 95%

// Hit?
if (MakeRandomFloat(0, 100) > chancetohit) {
//this->Message(MT_Emote, "You missed your target");
//this->Message_StringID(M,GENERIC_MISS,"You","your target.");
target->Damage(this, 0, 0xffff, 0x07);
}
else {
const Item_Struct* RangeItem = RangeWeapon->GetItem();
const Item_Struct* AmmoItem = Ammo->GetItem();
uint16 WDmg = RangeItem->Common.Damage;
uint16 ADmg = AmmoItem->Common.Damage;
int lev=CastToClient()->GetAAStruct()->class_skills.named.archery_mastery;
int mod = 0;
if(lev==0){mod=1;}
else if(lev==1){mod=1.3;}
else if(lev==2){mod=1.6;}
else if(lev==3){mod=2.0;}

uint16 levelBonus = (GetSTR()+GetLevel()+GetSkill(ARCHERY)) / 100;
uint16 MaxDmg = (WDmg+ADmg)*levelBonus*mod;

sint32 TotalDmg = 0;
sint32 critDmg = 0;



if (MaxDmg == 0)
MaxDmg = 1;
TotalDmg = (1 + MakeRandomInt(0, MaxDmg));
if(GetClass()==RANGER) {
critDmg = (sint32)(TotalDmg * 2);
}
if(target->IsClient()){ //Tone down pvp damage
if(critDmg>0)
critDmg-=critDmg/4;
TotalDmg-=TotalDmg/4;
}
if ((GetClass()==RANGER)&&((GetAAStruct()->pop_ability.named.headshot)==1)&&((target->GetLevel()) <= (this->GetLevel()-20))&&(MakeRandomInt(0,100) >= 75)&&(target->IsNPC()))
{ //headshot
entity_list.MessageClose(this, false, 50, 0, "%s scores a HEADSHOT!", this->GetName());
target->Damage(this, 32000, 0xffff, 0x07);
}
// no crits before level 12 cap is maxed //todo make crits based on AA for other classes
else if((GetClass()==RANGER)&&(GetSkill(ARCHERY)>65)&&(MakeRandomInt(0, 500) < (GetSkill(ARCHERY)+playerDex)/2)) {
if(target->IsNPC() && !target->IsMoving() && !target->IsRooted() && this->GetLevel()>50){
if(this->GetGM())
{
Message(0,"(GM ONLY) Doubling attack damage, npc isnt moving!");
critDmg*=2;
}
}
char val1[20]={0};
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, CRITICAL_HIT, GetName(), ConvertArray(critDmg,val1));
//this->Message_StringID(MT_CritMelee,CRITICAL_HIT,GetName (),ConvertArray(critDmg,val1));
//this->Message(MT_CritMelee, "You score a critical hit!(%d)", critDmg);
target->Damage(this, critDmg, 0xffff, 0x07);
}

else {
if(GetClass()==RANGER && !target->IsMoving() && !target->IsRooted() && this->GetLevel()>50){
if(this->GetGM())
{
Message(0,"(GM ONLY) Doubling attack damage, npc isnt moving!");
TotalDmg*=2;
}
}
char hitname[64]={0};
strncpy(hitname,target->GetName(),strlen(target->GetName())-2);
//char val1[20]={0};
//Message_StringID(MT_Emote,HIT_NON_MELEE,"You",hitname,ConvertArray(TotalDmg,val1));
//this->Message(MT_Emote, "You Hit for a total of %d non-melee damage.", TotalDmg);
target->Damage(this, TotalDmg, 0xffff, 0x07);
}
}

// See if the player increases their skill - with cap
float wisebonus = (GetWIS() > 200) ? 20 + ((GetWIS() - 200) * 0.05) : GetWIS() * 0.1;

if (((55-(GetSkill(ARCHERY)*0.240))+wisebonus > MakeRandomFloat(0, 100)) && (GetSkill(ARCHERY)<(m_pp.level+1)*5) && GetSkill(ARCHERY) < 252)
this->SetSkill(ARCHERY,GetSkill(ARCHERY)+1);
}
break;
}


Flurry, i made it 5, 10, 20% chance per lev based on something i read somewhere and just guessed and made it a 50% chance at 2 extra attacks when it triggers, also im not exactly sure how raging flurry works, from the wording it sounds like it might increase the chance of the second attack happening however a friend said it improves the chance of flurry happening by 10% per rank, anyone know how this works? i also made the flurry report an area thing with a range of 30 just cause well i think its cooler looking
zone\client_process.cpp around line 5336 add-

if(((CastToClient()->GetAAStruct()->class_skills.named.flurry) >= 1)&&(IsAttackAllowed(target))
&&(CastingSpellID()==0)&&(CombatRange(target)))
{ //Dook- Flurry AA
int lev=0;
lev=CastToClient()->GetAAStruct()->class_skills.named.flurry;
float rana = MakeRandomFloat(0, 1);
float ranb = MakeRandomFloat(0, 1);
if((lev == 1)&&(rana >= 0.95))
{
entity_list.MessageClose(this,false,20,13,"%s unleashes a FLURRY of attacks on %s!", GetName(), target->GetCleanName());
Attack(target,13);
if(ranb >= 0.5){Attack(target,13);}
}
else if((lev == 2)&&(rana >= 0.90))
{
entity_list.MessageClose(this,false,20,13,"%s unleashes a FLURRY of attacks on %s!", GetName(), target->GetCleanName());
Attack(target,13);
if(ranb >= 0.5){Attack(target,13);}
}
else if((lev == 3)&&(rana >= 0.80))
{
entity_list.MessageClose(this,false,20,13,"%s unleashes a FLURRY of attacks on %s!", GetName(), target->GetCleanName());
Attack(target,13);
if(ranb >= 0.5){Attack(target,13);}
}
}


Ambidexterity heard things from 7% to %10 so i went with %10
also in client_process.cpp around line 5392 add-


if(CastToClient()->GetAAStruct()->class_skills.named.ambidexterity == 1)
{
DualWieldProbability = (GetSkill(DUAL_WIELD) + GetLevel()) / 354.5f; // 10% for ambidexterity
}


anyway thats all i got thats workable so far, more to come, anyone fixed wake the dead yet? i have no idea where to even start.

Branks
08-12-2004, 11:20 AM
Temp Fix for MGB, far from perfect but it casts AE buffs and doubles manacost, also tries to affect NPCS, i know theres really no need for this on EMU servers due to the low population but /shrug.

zone\client.cpp replace exsisting with--

case 35: //MGB---AE cast group spell in slot 1
{
targ=ct;
int cur_level=CastToClient()->GetAAStruct()->class_skills.named.mass_group_buff;
if(cur_level == 1)
{
CastToClient()->Message(0,"Casting Spell in Slot 1 as an Area Effect");
int spell=m_pp.mem_spells[0];
if((IsGroupSpell(spell))&&(!IsEffectInSpell(spell, SE_Gate))&&
(!IsEffectInSpell(spell, SE_Translocate))&&(!IsEffectInSpell(spell, SE_Teleport))
&&(!IsEffectInSpell(spell, SE_Succor)))
{
int mana;
mana = spells[spell].mana;
mana = (GetActSpellCost(spell, mana))*2;
if(c->GetMana() >= mana)
{
int newmana=(c->GetMana() - mana);
entity_list.AESpell(c,c,100,spell);
c->CastSpell(spell,ct,9,0,0,0,0);
c->SetMana(newmana);
}
else
{
c->Message(13,"Insufficient Mana to cast this Spell.");
break;
}
}
else
{
c->Message(0,"MGB only works with Group Buffs!");
break;
}
int usemod=CastToClient()->GetAAStruct()->god_ability.named.quick_mass_group_buff;
int time;
if(usemod == 1){time=3888;}
else if(usemod == 2){time=3456;}
else if(usemod == 3){time=3024;}
else{time=4320;}
timermod=time;
break;
}
else
CastToClient()->Message(0,"You have not learned this skill");
}
break;


and heres something else i did while messing around, could be a fun way to remove extra plat from a server while beg doesnt work, its just a throw command inspired by the final fantasy games of course.

zone\client_process.cpp replace exsisting with----

case OP_Begging: //Throw command final fantasy style--
{
int p=m_pp.platinum;
int g=m_pp.gold;
int s=m_pp.silver;
int c=m_pp.copper;
Mob* target=CastToClient()->GetTarget();
int toss=(p*10)+(g*1)+(s*0.1)+(c*0.01);
if(toss>0)
{
if(target->IsAttackAllowed(target)&&(target->GetLevel()<=50))
{
int mana=CastToClient()->GetMana();
CastToClient()->DoAnim(5);
entity_list.MessageClose(this,true,50,0,"%s throws loose change at %s!", this->GetName(), target->GetCleanName());
CastToClient()->Message(0,"You Throw loose change at %s!", target->GetCleanName());
target->Damage(CastToClient(), toss, 0xFFFF, 0);
CastToClient()->SetMana(mana);
AddMoneyToPP(-c,-s,-g,-p,true);
}
else
{
CastToClient()->Message(0,"You don't think %s would be affected by coins, do you?", target->GetCleanName());
}
}
else
{
CastToClient()->Message(0,"To Throw change you must have change!");
}
break;
}

Branks
08-19-2004, 12:17 PM
ok almost have swarm pets and wards done, however i need a lil more info about them, ive looked almost everywhere i can think of and havent had any luck getting details of what exactly some of them do, i understand the basics of most of them however i need more details on things like max hit on the AA swarm pets, max hit on the proc pets and info on the spells that the wards cast and how often they cast it and at what range etc etc, also details on the models would be really handy, i know the wizard swords and some of the proc pets are invis men with epics of the class however the SK one seems to be a skeleton instead, are any other class pet procs also other models than invis men? i also read that the call of time pet has a max hit of 415 which seems a lil off to me so was hoping for a second opinion.

swarm of decay is supposed to be skeleton archers, hows this work? are they rooted in place and just use archery i guess? yes, no? max hit? servant of ro, whats this do other than the base description, is the pet rooted? what spell does it cast?

anyway as you can see im missing a lot of minor details about a lot of these skills so if you know anything to be 100% correct please let me know so i can do these right the first time

is there any problem with me claiming bodytype 63 for temporary pets? its labeled as an unknown bodytype but was wondering if this had been updated somewhere that i dont know of, also im currently having some problems finding the location of the code that limits characters to 1 familiar at a time, ive tried tons of things to remove this temporarily however it never seems to work, is there something i dont know about the way familiars are handled?
currently im just making the pets despawn whenever their target gets below 2% or so health, however this is a problem and as they "can" ks players.

also thanks to everyone who helped when i booted my server publicly a few days ago i got a lot of usefull information, thanks again. if anyone knows any details of these skills or any others whos description is a lil off (doppelganger) please fill me in, yes ive tried all the basic sites like steel warriors allakhazam's and lucy but their all proving to be 99% useless to me.

Xabob
08-19-2004, 01:18 PM
Jesus nice work man

killspree
08-19-2004, 01:53 PM
What exactly does that begging code do? It takes the money you have on you and converts it into damage and throws it?

Branks
08-19-2004, 02:15 PM
heh yeah it just takes the money on you and does 10 damage per plat, i did the lil attack animation and things also with it and if your curious as to why the Mana parts are in there well, at first it was causing hotkeys to lock up and for whatever reason adding the current mana bit fixed this, i honestly dont know how or why it fixed it but i had done some other skill on the beg button before and it never had a problem locking up, so i just went through the process of eliminations with the 2 and found that when i added some change to mana on it they no longer locked up....sorry thats the only explanation i have and also even with the manachange once every now and then it still seems to lock up for some people on my server, guess its something to do with patch state but really no clue. anyway im slowly creating a server with a few friends and i was just playing with that and they thought it was a really fun/neat command so i just thought id share it.

bluejam
08-19-2004, 03:07 PM
Damn, nice job there Branks.

I hope the server admins can work with that.

monalin crusader
08-19-2004, 11:54 PM
Definatly something that saves me alot your knocking out alot of aa's. I'm working on some stuff of my own soon too that u guys can use but. Dam nice job bro.

Branks
08-20-2004, 03:09 PM
thanks for the compliments, nice to know someone considers this usefull, anyway heres the progress at the moment, i just completely fixed swarm pets working 100% correctly except the fine details of models/max hit etc, currently i have them labeled as pets, despawning correctly and everything else is done so they no longer can KS players, and work just as they do on live with the exception of gaining a second target when the original target dies, (ok so 99% correct) i'll work on this. i'll put the code on here as soon as i remove all my comments and testing stuff statments.

however it wont be complete because i cant seem to find information anywhere at all on the correct damage and models of the pets, nor information on what exactly the wards cast, so ill just put in a minor list of what i know

mage swarm pets are size 3 earth elementals with a max hit of around 50

wizards = call of xuzl pets, hit 50ish

shaman pets = spirit wolves hit 50ish

mage servant of ro = fire elemental that casts some spell? normal size

PoP pet weapon procs= invis man with the class epic with the exception of the SK weapon which the model is a skeleton, these have a max hit of 90ish

call of wu monk pet proc...whats this one wield, is the epic visable? or does it even wield the epic?

call of time...hearing its somehting that looks like the spear from solusek ro and has a max hit 415?

tricksters calling and stone animation im guessing are NPC spells however if anyone knows details on these please let me know also since their temporary pets also and it would be nice to see them working correctly

swarm of decay...im guessing rooted skeletons with bows?

wards....invis man that casts some unknown spells

should i maybe post these questions in another forum? ive got a lil usefull info from leaving the server up the last 2 days but mainly people just seem to manaburn each other in the arena 2 dozen times and log out.

im also pretty close to the timer check thing to not allow reuse untill the timer has expired but currently its not 100% and causing skills to only be used once per zone

also another problem ive found is that the spell ids change with each patch and when the server and client list dont match this causes issues and while the spell ids are in the code itself its kinda useless, i cant think of anything to correct the mismatch of client/server however the IDs need to be removed from the code so i was wanting to put in another column in alt_vars with the spell ids for each skill along side their cost and max level this way as the server is updated people could use an sql file to make AAs work with the new spells lists, however currently im not too sure how to do this. but plan to work on it, however if anyone else has done this or wants to feel free, id appreciate it

anyway thats all for now ill work on getting the swarm code cleaned up a bit and working more like normal pets and post is a lil later

Ace
08-20-2004, 03:50 PM
If it's helpful any, my bard pet weapon (Coral Hilted Shortsword) proc'd a pet which hit for 94 maximum. It may have been 96, but I am unsure. I am completely positive that it hit for at least 94. The pet also kicks and bashes, but I cannot remember those damage numbers offhand.

If you need any info with the pet weapon, give me a shout and I can test it in game.

I would assume the other pet weapons follow this damage pattern as well.

Branks
08-20-2004, 06:46 PM
thats what i was looking for, thanks!

Ace
08-20-2004, 11:13 PM
Again, if you need anymore info, shoot me a PM and I can get it for you.

monalin crusader
08-22-2004, 01:46 AM
prevents spell 2821 from being cast, so does anyone know how i could make 2821 an allowable spell for HT since im pretty sure it is correct, but i may be wrong since ive never played an SK myself.

try this it kinda defeats teh purpose of having this line in here for those spells but it just allows the spell id u want to get through to work. And yes the HT spell does get more powerful as u get 40+ It also gets alot harder to resist and does a heck of a lot more dmg. My sk at 65 on the emulator only does 700 for an HT at 65 and thats wrong hehe.

if((spell_to_cast != castspell->spell_id) && (spell_to_cast != 2821)
{
InterruptSpell(castspell->spell_id); //CHEATER!!!
break;
}

Also i've been looking into the pets recently and they're casting warders because there is no data in the DB for it to cast the spell. When it looks in the DB for the correct pet it cant find it and casts a default pet spell. I'm not sure where thats located in the code or even if its in the db. I can look around a little and see if that helps.

Branks
08-22-2004, 02:58 AM
the pet code is in zone\spells.cpp and it has defaults for anything thats not already listed in "pets" in the DB, i think you may be mistaken as to what i was speaking of, of wards, i meant the wards that are summoned for the AA skills such as ward of destructions and others, clerics and shaman get ones that casts an AE heal for a duration of time and wizards get one that does damage and maybe a few other classes ive forgoten at the moment.

ive also been told of a bug with some pets spawning level 200+ which i'll look into sometime since ive become quite familiar with the whole pet making process due to the swarm pets, also as an update to those, sorry no code yet but i found a new bug with them, currently if you have a pet and use them your real pet despawns with them, im working on correcting this atm but not making much progress. my newest plan is to try and find a way to add an extra spot or use an unknown as a swarm pet ID in the player profile to solve the problem of pets questioning whom their owner is and then despawning, although im not all too sure if thats even possible, regardless currently its not quite right and its a lot of code which ive already completely redone 3 times nows and still having problems so id rather not waste another full page on this thread for something that i may redo tommorow, if anyone wants to play with their current state you can log into my server ive had up a few days now and i guess ill keep up awhile longer as its been rather usefull for gathering information on many of the AA skills, or PM me and ill send you the current codes ive got.

also, has anyone fixed this items vanishing bug when you zone? im hearing its a common bug but i havent had much luck correcting it yet. anyway thats all for now.

sotonin
08-22-2004, 05:11 AM
rangerdown posted a fix for the pets spawning uber. for 1 pet the summoned mistwalker. perhaps the same logic could be used to fix the others. i beleive its in the bug forums somewhere

monalin crusader
08-22-2004, 05:44 AM
i think you may be mistaken as to what i was speaking of, of wards

Hehe Yes i was i dunno what i was thinking doh. =P[/code]

Branks
08-23-2004, 03:02 PM
here a solution to the overpowered pets bug/problem, i havent seen rangerdown's post so sorry if its the same thing, anyway this will simply making any pet thats unknown to the code/database, a lev 10 gnome with a max hit of 10 and display a message in zone.exe stating the character id of the caster and the spell id used with the unknown pet so that you can go through and update them. im not exactly sure how the exsisting code for default pets was supposed to work however it seems it was getting the raw information from the spell being cast and trying to create a pet from that, maybe the way pet spells are made have been changed? dont know, anyway it was multiplying things it shouldnt have in an attempt to make a pet from the spell data and well wasnt working correctly, thus we had lev 200+ pets.


in zone\spells.cpp around line 6472 if youve been useing any of the other code ive been posting.

otherwise do a search for "spell property testing functions" and scroll up a few lines till you find the default case for for MakePet and replace the exsisting code between "default:" and "break;"
with


default:
CastToClient()->Message(0,"Unknown Pet Type! Tell your GM to Update! for now enjoy your gimp!");
int chid=CastToClient()->CharacterID();
int spel=casting_spell_id;
cout<<"Unknown pet type being created by Character ID "<<chid<<" in Spell ID "<<spel<<endl;
strcpy(npc_type->name, "Gimpy");
npc_type->size = 2;
npc_type->level = 10;
npc_type->race = 12;
npc_type->gender = 0;
npc_type->texture = 1;
npc_type->min_dmg = 1;
npc_type->max_dmg = 10;
npc_type->max_hp = 200;
break;


excluding the "default:" and "break" of course.

edit- I'll learn to type someday.

sotonin
08-23-2004, 03:12 PM
why gnome? make it a puppy or a rat. =D

Branks
08-23-2004, 07:09 PM
puppy > gnome. just cant touch the gimpness that is gnomes, anyway uh heres a few other AAs, and im redoing manaburn and lifeburn so their pvpable will update that in a moment. swarm pets still buggy so no code yet but ive almost got enough information from people that their all the correct models now. no luck on the wards yet...

redid SK weapon proc buffs to make them work correctly.
soul abrasion.
healing adept.
advanced healing adept.
healing gift.
advanced healing gift.
casting fury.
fury mastery.
fury of magic mastery.
theft of life.
removed the FD effect of lifeburn server side which was causing issues.
added a message to heals for caster and target.


zone\spells.cpp search for " nukes, heals; also "

and replace the exsisting case: SE_CurrentHP with


case SE_CurrentHP: // nukes, heals; also regen/dot if a buff
{
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Current Hitpoints: %+i", effect_value);
#endif

// SE_CurrentHP is calculated at first tick if its a dot/buff
if (buffslot >= 0)
break;

// for offensive spells check if we have a spell rune on
sint32 dmg = effect_value;
if(dmg < 0)
{
// take partial damage into account
dmg = (int) (dmg * partial / 100);
if (caster && caster->IsClient())
{
dmg = caster->GetActSpellValue(spell_id, dmg);

//Dook- Soul Abrasion, 3 levs, increase self buff procs damage 40% each
if(caster->CastToClient()->GetAA(89))
{
if((spell_id==2718) ||
(spell_id==2712) ||
(spell_id==1471) ||
(spell_id==3228) ||
(spell_id==4910) ||
(spell_id==4908))
{
uint8 lev=0;
lev=caster->CastToClient()->GetAA(89);
if(lev==1){dmg=dmg*1.67;}
else if(lev==2){dmg=dmg*2.34;}
else if(lev==3){dmg=dmg*3.01;}
}
}

//spell crits
int chance = 0;
float ratio =1.0;

//normal spell crit for wizards
if(caster_level >= 11 && caster->GetClass() == WIZARD)
{
chance+= 7;
ratio +=.15;
}

//spell casting fury, fury mastery, and fury of magic mastery. Dook-
uint8 scf = 0;
uint8 scfm = 0;
uint8 cfom = 0;
uint8 fomm = 0;
uint8 cfomm = 0;
scf = caster->CastToClient()->GetAA(23);
scfm = caster->CastToClient()->GetAA(114);
cfom = caster->CastToClient()->GetAA(215); //cleric
fomm = caster->CastToClient()->GetAA(216);
cfomm = caster->CastToClient()->GetAA(260); //cleric only?
if(scf == 1) {chance+=2; ratio += .333;}
if(scf == 2) {chance+=5; ratio += .666;}
if(scf == 3) {chance+=7; ratio += 1.0;}
if(scfm == 1){chance+=3;}
if(scfm == 2){chance+=5;}
if(scfm == 3){chance+=7;}
if(fomm == 1){chance+=2;}
if(fomm == 2){chance+=4;}
if(fomm == 3){chance+=6;}
if(cfom == 1){chance+=2;}
if(cfom == 2){chance+=4;}
if(cfom == 3){chance+=6;}
if(cfomm == 1){chance+=2;}
if(cfomm == 2){chance+=4;}
if(cfomm == 3){chance+=6;}

int r=MakeRandomInt(0,100);
if((r <= chance)&&(spell.targettype!=6))
{
dmg = (int)(dmg * ratio);
entity_list.MessageClose(this, false, 75, 0, "%s delivers a critical blast! (%d)", caster->GetCleanName(), ((dmg)*(-1)));
caster->Message(0,"You deliver a critical blast! (%d)", ((dmg)*(-1)));
}
}

sint32 origdmg = dmg;
dmg = ReduceMagicalDamage(dmg, GetMagicRune());
if (origdmg != dmg && caster)
{
caster->Message(15,
"The Spellshield absorbed %d of %d points of damage",
abs(origdmg - dmg), abs(origdmg));
}

if (dmg == 0) // rune absorbed it all
break;
}
else if(dmg > 0)
{
if (caster && caster->IsClient())
{
dmg = caster->GetActSpellValue(spell_id, dmg);
int dur=spell.buffduration;

//Dook- Healing Adept and Advance Heal Adept
uint8 ha = 0;
ha = caster->CastToClient()->GetAA(18);
if((dur==0)&&(spell_id!=13)&&(ha>=1))
{
uint8 aha = 0;
aha = caster->CastToClient()->GetAA(146);
if(ha==1 && aha==0){dmg=dmg*1.02;}
else if(ha==2 && aha==0){dmg=dmg*1.05;}
else if(ha==3 && aha==0){dmg=dmg*1.10;}
else if(ha==3 && aha==1){dmg=dmg*1.13;}
else if(ha==3 && aha==2){dmg=dmg*1.16;}
else if(ha==3 && aha==3){dmg=dmg*1.19;}
}

//heal crits
int chance = 0;
float ratio =1.0;

//Remove next 5 lines if you dont want innate cleric crit heals
if(caster->GetLevel() >= 11 && caster->GetClass() == CLERIC)
{
chance+= 5;
ratio +=.15;
}

//healing gift, advance HG, Dook-
uint8 hg=0;
uint8 ahg=0;
hg=(caster->CastToClient()->GetAA(19));
ahg=(caster->CastToClient()->GetAA(147));
if(hg == 1){chance+=3; ratio += .333;}
if(hg == 2){chance+=6; ratio += .666;}
if(hg == 3){chance+=10; ratio += 1.0;}
if(ahg == 1){chance+=2;}
if(ahg == 2){chance+=2;}
if(ahg == 3){chance+=2;}

if(MakeRandomInt(0,100) <= chance)
{
dmg = (int)(dmg * ratio);
entity_list.MessageClose(this, false, 75, 0, "%s performs an exception heal! (%d)", caster->GetName(), dmg);
caster->Message(0,"You perform and exceptional heal! (%d)", dmg);
}
}
if(((this->GetHP())+dmg) >= (this->CalcMaxHP()))
{
dmg=((this->CalcMaxHP())-(this->GetHP()));
}
if(this->IsClient())
{
this->Message(1,"%s has healed you for %d point of damage.", caster->GetCleanName(), dmg);
}
if(caster->IsClient())
{
caster->Message(1, "You have healed %s for %d points of damage.", this->GetCleanName(), dmg);
}
}
this->ChangeHP(caster, dmg, spell_id, buffslot);
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Current Hitpoints: %+i actual: %+i", effect_value, dmg);
#endif
break;
}



do a search for "SE_WeaponProc:" and replace exsist case with this


case SE_WeaponProc:
{
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, effect_value);
#endif


if(spell_id==2574)//scream of death
{
AddProcToWeapon(2718);
break;
}
if(spell_id==2576)//mental corruption
{
AddProcToWeapon(2712);
break;
}
if(spell_id==1459)//shroud of death
{
AddProcToWeapon(1471);
break;
}
if(spell_id==1376)//shroud of undeath
{
AddProcToWeapon(1471);
break;
}
if(spell_id==1459)//shroud of death
{
AddProcToWeapon(1471);
break;
}
if(spell_id==3227)//shroud of chaos
{
AddProcToWeapon(3228);
break;
}
if(spell_id==4903)//black shroud
{ //procs 4910
AddProcToWeapon(4910); //then 4911 to client
break;
}
if(spell_id==4902)//mental horror
{ //procs 4908
AddProcToWeapon(4908); //then 4909 to the client
break;
}
else
AddProcToWeapon(spell.base[i]);
break;
}


now on to zone\attack.cpp do a search for "if spell is lifetap" and make sure your at the second one around like 1600 something since there seems to be the exact same code in 2 spots for some reason i dont know. replace exsisting to


// if spell is lifetap add hp to the caster
if (other && IsLifetapSpell( spell_id ))
{
int32 healedhp=damage;

//Dook-Theft of Life
if((other->CastToClient()->GetAA(214)) >= 1)
{
int chance = 101;
float ratio = 0;
int tol=0;
tol=other->CastToClient()->GetAAStruct()->pop_ability.named.theft_of_life;
if(tol==1){chance=97; ratio=1.333;}
if(tol==2){chance=94; ratio=1.666;}
if(tol==3){chance=90; ratio=2.000;}
if((MakeRandomInt(0,100)) >= chance)
{
healedhp=damage*ratio;
entity_list.MessageClose(other,false,75,0,"%s performs an exceptional heal! (%d)",other->GetName(),healedhp);
other->Message(0,"You perform an exceptional heal! (%d)",healedhp);
}
else
{
healedhp=damage;
}
}

// check if healing would be greater than max hp
// use temp var to store actual healing value
if ( other && other->GetHP() + healedhp > other->GetMaxHP()) //healedhp was damage
{
healedhp = other->GetMaxHP() - other->GetHP();
other->SetHP(other->GetMaxHP());
}
else
{
// healedhp = damage; //testing
if(other != 0)
other->SetHP(other->GetHP() + healedhp); //was damage
}


// if client was casting the spell there need to be some messages
if (other->IsClient())
{
other->CastToClient()->Message(4,"You have been healed for %d points of damage.", healedhp);
}

// emote goes with every one ... even npcs


then back into zone\spells.cpp do a search for "SE_FeignDeath"
after the #endif add


if(spell_id==2488) //Dook- Lifeburn fix
break;


couple more in a few.

Cisyouc
08-24-2004, 12:36 AM
puppy > gnome

Die!! Gnome > ALL!

sotonin
08-24-2004, 01:04 AM
is this stuff being added into the CVS ? please say that it is =p

Branks
08-24-2004, 06:01 AM
would be pointless till i get the timers working correctly, for anything other than none legit servers. currently i can put in a check for them each time you zone but they dont refresh so you can only use a skill once per zone. plus all of these need a little finishing touches because i dont know the exact values of some skills and have just gone by "feel" and guesstimates from players.

also ive been looking at the way LoH and HT work and they seem to do the same thing in that they dont update untill you zone. id really like to hear from some of the devs about this since im still extremly newbish with all this and would like to know if ive made any common mistakes and also if it would be a bad thing to have 20 or so timers running for each client in order to make AAs refresh correctly, i had to add a new timers for swarm pets and noticed no performance loss however that was only one timer, would it be an issue to have several running? also is there anywhere i can find a list of the message types in order to properly do messages so that they filter correctly and crits etc dont show up when you use the options to turn them off? anyway in a bit of a rush ill be back in a few hours.

sotonin
08-24-2004, 08:44 AM
last i heard scorp got timers working correctly... ?? maybe im wrong.

Branks
08-24-2004, 09:53 AM
scorp also has a ton of custom code i believe so it may not work the same with this, however if it does and he feels like sharing that would be great! if not no biggy i'll eventually get it done or someone else will.

Branks
08-24-2004, 02:45 PM
updated the code from my last post it seems while testing none of us ever decided to use canni, manastones etc or heal a pet so it was causing some problems we apparently didnt see, sorry ill try to be a lil more carefull testing next time.

anyway uh updated it so self target only spells no longer crit(manastone-canni-etc) and fixed the heal messages a lil but currently group heals dont display a message- also fixed something else i cant think of atm.

Branks
08-28-2004, 06:49 AM
dont use old manaburn or lifeburn code, remove them and use the new stuff posted below, this will allow the buff from manaburn to take hold and not allow manaburn groups however the buff stacking system doesnt seem to work with it currently- also this method allows pvp checks and you dont have to modify the spell value.

also updated the previous code for zone/spells.cpp to include a few more things and updated it since i learned a little more of the way spells are handled. case SE_CurrentHP that is.

added code to place a cap on pvp damage of 70% for a single spell like live used to be, if you want it 40% like live is currently youll have to do it yourself.

added cleric fury and fury of magic mastery, im not too sure of the exact values of these AAs so i just guessed that its a little behind the other versions.

also added quick damage, quick evacuation and spell casting deftness. i think theres another spell haste AA but cant think of it currently. will update whenever i do

also swarm pets are still killing exsisting pets and i have yet to find a way around this but im working on it.

zone/spells.cpp right below case SE_CurrentHP youll find
case: SE_CurrentHPOnce- replace exsisting with this-


case SE_CurrentHPOnce: // used in buffs usually, see Courage
{
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Current Hitpoints Once: %+i", effect_value);
#endif
//Dook- added manaburn, lifeburn
if(spell_id==2751)
{
int r=MakeRandomInt(0,10);
if(r>=9)
{
effect_value+=((caster->GetMana())*2.4)*-1;
caster->SetMana(0);
entity_list.MessageClose(caster,false,75,0,"%s delivers a critical blast! (%d)",caster->GetName(),((effect_value)*(-1)));
caster->Message(0,"You deliver a critical blast! (%d)", ((effect_value)*(-1)));
}
else
{
effect_value+=((caster->GetMana())*1.8)*-1;
caster->SetMana(0);
}
}
if(spell_id==2755)
{
effect_value+=(caster->GetHP())*-1;
caster->SetHP(caster->CalcMaxHP()/4);
}
ChangeHP(caster, effect_value, spell_id, buffslot);
break;
}


then in zone/attack.cpp do a search for "cut all pvp" and alter the exsisting code to be-


if (amount < 0)
{
// cut all PVP spell damage to 2/3 -solar
if(other && this->IsClient() && other->IsClient() && this != other)
amount = (int) (amount * 0.67f);
//Dook- Added 70% single blow max damage --pvp dmg cap
if(other && this->IsClient() && other->IsClient())
{
int pcmaxdmg=(((this->CalcMaxHP())*0.7)*(-1));
if(amount<pcmaxdmg)
amount=pcmaxdmg;
}
this->Damage(other, abs(amount), spell_id, 231, false, buffslot, iBuffTic);
return true;
}


then in zone/spells.capp again do a search for "we know our" and alter exsisting code to look like this-


// we know our mana cost now
casting_spell_mana = mana_cost;

//Dook- Casting Haste
if((IsClient)&&(spell_id != 13)&&(slot != 9)&&(slot != 10)&&(cast_time >= 4000))
{
int dur=spells[spell_id].buffduration;
int dmg;
for (int i = 0; i < EFFECT_COUNT; i++)
{
if (spells[spell_id].effectid[i] == SE_CurrentHP)
{
dmg = CalcSpellEffectValue(spell_id, i, GetCasterLevel());
break;
}
}
Client *c=this->CastToClient();
if(IsEffectInSpell(spell_id, SE_Succor)) //Dook- Quick Evac
{
uint8 qe=c->GetAA(42);
if(qe==1){cast_time=(cast_time*0.90);}
if(qe==2){cast_time=(cast_time*0.75);}
if(qe==3){cast_time=(cast_time*0.50);}
}
if((IsEffectInSpell(spell_id,SE_CurrentHPOnce))||
(IsEffectInSpell(spell_id,SE_CurrentHP))&&(dmg<=0) )
{
uint8 qd=c->GetAA(44);
if(qd==1){cast_time=(cast_time*0.98);}
if(qd==2){cast_time=(cast_time*0.95);}
if(qd==3){cast_time=(cast_time*0.90);}
}
if(IsBeneficialSpell(spell_id)&&(dur > 0))
{
uint8 deft=c->GetAA(27);
if(deft==1){cast_time=(cast_time*0.95);}
if(deft==2){cast_time=(cast_time*0.85);}
if(deft==3){cast_time=(cast_time*0.75);}
}
else if(cast_time <= 0)
{
cast_time = 0;
}
}

orgcasttime = cast_time;

// cast time is 0, just finish it right now and be done with it
if(cast_time == 0)


thats all for now.

Branks
09-02-2004, 03:32 AM
updated my little checklist of whats broken in my first post, you dont need to do anything with that i simply did it in hopes that someone will pick one of the none working one and start hacking at it with me.

also updated the flurry code from an earlier post, the part in client_process.cpp due to the message being displayed at incorrect times such as when the target was out of range and the skill triggered.

updated SE_CurrentHP in spells.cpp from an earlier post due to something allowing a warrior to get an exceptional heal....only happened onces and i dont really know why but i cleaned it up a little and it hasnt happened since.

updated the lifetap code in attack.cpp from an earlier post due to once again something without the skill got the benefit and a necro pet this time had an exceptional heal... anyone see something obviously wrong im missing?

so! ive spent a ton of time with swarm pets and and have yet to get them perfect, so im posting the progress ive made with them currently in hopes that someone will help finish up, the current minor issues are commented in the code for things like incorrect textures/models or details i dont know of them, the only magor issue at the moment is that after the swarm pets despawn if you had a pet already you no longer see the pet in the group window or in the pet information window, however all command line instructions work perfectly still, this one is driving me insane as ive tried just about everything i believe to be possible. also since this isnt exactly finished im not removing my comment or custom pets i threw in for fun.

wake the dead and doppelganger, these both require getting textures from pop+ which ive been unable to do and havent spent much time looking into yet. so doppelganger only trys to reproduce the primary item slot from the caster and i just gave it a kedge robe for the time being.

wake the dead, again with the textures thing, it works out nicely for NPC corpses but its far from perfect with clients.

fading memories and escape, the invisibility effect on these isnt working correctly since i dont yet understand how to make a client use their hide skill by code, and when i just flagged the player invisable the effect doesnt fade thus every mob in the zone cons indifferent after the skill had been used, as a temporary solution i added the spell improved invis to the skills and plan on coming back to this later, also when i know for sure if fading memories uses 900 mana or only checks that the player has 900 mana.

rampage...well it works perfectly, but i added an area message to it just as i did with flurry, just cause well i think its more fun that way~

ae taunt... see rampage

the god swarm pets i havent been able to get much information on, i know the shaman swarm pets from god proc a 640 poison based DD however i havent been able to figure out what spell this is.

swarm of decay, again with the freakin texture thing, their bows are not the correct model, i also had to guess as to their attack animation speed since it seems no one has seen it enough to remember.

anyway i think thats the magority of it and instead of posting the code per skill im just lumping it all together here, also keep in mind this is a work in progress so dont expect perfection with this just yet.

zone\MobAI.cpp search for "Mob::AI_Process" then scroll down a few lines till you see the bit saying "if (CombatRange(target))" then ABOVE THAT LINE add.


if((GetBodyType()==63)&&(GetClass()==4)
&&(attack_timer->Check())&&(IsAttackAllowed(target)))
{ //Dook- Swarm Pets -Swarm of Decay
if(Dist(*target)<=100)
{
FaceTarget(target);
DoAnim(20, 9);
int dmg=MakeRandomInt(50,200);
target->Damage(this, dmg, 0xffff, 0x07, true);
}
return;
}

if((GetBodyType()==63)&&(GetRace()==89)&&(IsAttack Allowed(target))
&&(attack_timer->Check())&&(Dist(*target)<=100))
{
//Dook- Servant of Ro castin Bolt of Lava
CastSpell(3005,target->GetID(),9,3000,0,0,0);
return;
}

if((GetBodyType()==63)&&(GetRace()==127)&&(IsAttac kAllowed(target))
&&(attack_timer->Check())&&(CombatRange(target))&&(GetClass()==90)
&&(MakeRandomInt(0,10)>=9))
{
CastSpell(1638,target->GetID(),9,0,0,0,0);
}

if((GetBodyType()==63)&&(GetRace()==120)&&(IsAttac kAllowed(target))
&&(attack_timer->Check())&&(CombatRange(target))&&(GetClass()==91)
&&(MakeRandomInt(0,10)>=9))
{
//Dook- ToDo Add GoD shaman swarm puppy proc here
}


now on to zone\entity.cpp do a search for "EntityList::GetFreeID" then ABOVE THAT LINE add the following.


Mob* EntityList::GetMobInZoneByRange(Mob *client, int type, int range) //Dook- AA skills
{
if(type==1) //Dook- find a corpse within range
{
LinkedListIterator<Corpse*> iterator(corpse_list);
iterator.Reset();
Mob* corp;
while(iterator.MoreElements())
{
corp = iterator.GetData();
if(corp->Dist(*client)<=range)
{
return iterator.GetData();
}
iterator.Advance();
}
return 0;
}
if(type==2) //Dook- todo add mob by range here
{
return 0;
}
}

void EntityList::WipeHateAll(Mob *client) //Dook- FM, Escape and such
{
LinkedListIterator<Mob*> iterator(mob_list);
Mob *agroed;

for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
{
agroed = iterator.GetData();
if(agroed->IsNPC())
{
agroed->RemoveFromHateList(client);
}
}
}

void EntityList::AETaunt(Mob *client) //Dook- AE Taunt of course..
{ //Dook- no horse no players
LinkedListIterator<Mob*> iterator(mob_list);
Mob *taunte;
for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
{
taunte = iterator.GetData();
if((taunte->Dist(*client) <= 30)&&(client->IsAttackAllowed(taunte))&&(taunte != client)
&&(taunte->IsNPC())&&(taunte->GetRace() != 216))
{
Mob* hated=taunte->GetHateTop();
int hate=0;
if(hated)
{
hate=taunte->GetHateAmount(hated);
taunte->SetHate(client,(hate+100));
}
else
{
taunte->AddToHateList(client,100);
}
}
}
}

void EntityList::AEAttack(Mob *attacker, float dist) //Dook- Rampage and stuff
{ //Dook- Will need tweaking, currently no pets or players or horses
LinkedListIterator<Mob*> iterator(mob_list);
Mob *curmob;

for(iterator.Reset(); iterator.MoreElements(); iterator.Advance())
{
curmob = iterator.GetData();
if((curmob->Dist(*attacker) <= dist)&&(attacker->IsAttackAllowed(curmob))&&(curmob != attacker)
&&(curmob->IsNPC())&&(curmob->GetRace() != 216))
attacker->Attack(curmob,13);
}
}


then on to zone\entity.h do a search for "GetMobByNpcTypeID" then above or below it, doesnt really matter add the following.


Mob* GetMobInZoneByRange(Mob* client, int type, int range);//Dook- For AA skills etc
void WipeHateAll(Mob* client); //Dook- Escape and Fading Memories etc
void AETaunt(Mob* client); //Dook- AE Taunt of course
void AEAttack(Mob *attacker, float dist); //Dook- Rampage and such


then on to zone\mob.cpp and do a search for
"attack_timer_dw = new Timer(2000);" then below this line add the following.


swarm_timer = new Timer(0); //Dook- swarm pets
swarm_timer->Disable();


then in mob.cpp still search for "safe_delete(spellend_timer);" and on the line below it add.

safe_delete(swarm_timer); //Dook- swarm pets


then still in moc.cpp do a search for "Mob* Mob::GetOwnerOrSelf" and replace exsisting with this.

Mob* Mob::GetOwnerOrSelf() {
if (!GetOwnerID())
return this;
Mob* owner = entity_list.GetMob(this->GetOwnerID());
if (!owner) {
SetOwnerID(0);
}
else if (owner->GetPetID() == this->GetID()) {
return owner;
}
else if (owner->GetFamiliarID() == this->GetID()) {
return owner;
}
else if (this->GetBodyType() == 63) { //Dook- swarm pets
return owner;
}
else {
SetOwnerID(0);
}
return this;
}


still in mob.cpp right below the code we just did you should see "Mob* Mob::GetOwner" replace exsisting with this.


Mob* Mob::GetOwner() {
Mob* owner = entity_list.GetMob(this->GetOwnerID());
if (owner && owner->GetPetID() == this->GetID()) {

return owner;
}
if (owner && owner->GetFamiliarID() == this->GetID())
{
return owner;
}
if(this->GetBodyType() == 63) //Dook- Swarm Pets
{
return owner;
}
this->SetOwnerID(0);
return 0;
}


now move over to zone\mob.h and search for "spellend_timer"
and right below this add.

Timer* swarm_timer; //Dook- swarm pets


now move to zone\npc.cpp and search for "if (p_depop)" and replace exsisting with.

if (p_depop)
{
Mob* owner = entity_list.GetMob(this->ownerid);
if((owner != 0)&&(this->GetBodyType() != 63)) //Dook- Swarm Pets
{
owner->SetPetID(0);
this->ownerid = 0;
this->petid = 0;
}
if(this->GetBodyType() ==63) //Dook- Swarm Pets
{
this->ownerid = 0;
this->petid = 0;
}
return false;
}


then move to zone\spdat.h and search for "SE_StackingCommand_Block" and alter that area to look like this.

#define SE_StackingCommand_Block 148
#define SE_StackingCommand_Overwrite 149
#define SE_DeathSave 150
#define SE_TemporaryPets 152 //Dook- Swarm Pets
#define SE_BalanceHP 153 // Divine Arbitration
#define SE_DispelDetrimental 154
#define SE_IllusionCopy 156 // Deception
#define SE_SpellDamageShield 157 // Petrad's Protection
#define SE_Reflect 158
#define SE_AllStats 159 // Aura of Destruction
#define SE_FadingMemories 194 //Dook- ....
#define SE_Blank 254
#define SE_WakeTheDead 299 //Dook- ....
#define SE_Doppelganger 300 //Dook- ...


then on to zone\spells.cpp and search for "Mob::SpellProcess" and add the bit at the bottom so that it looks like this.

void Mob::SpellProcess()
{
// check the rapid recast prevention timer
if(delaytimer == true && spellend_timer->Check())
{
spellend_timer->Disable();
delaytimer = false;
return;
}

// a timed spell is finished casting
if (casting_spell_id != 0 && spellend_timer->Check())
{
spellend_timer->Disable();
delaytimer = false;
CastedSpellFinished(casting_spell_id, casting_spell_targetid, casting_spell_slot, casting_spell_mana, casting_spell_inventory_slot);
}

//Dook- swarm pets
if((swarm_timer->Check()) && (GetBodyType() == 63))
{
Depop();
swarm_timer->Disable();
}
}


then still in spells.cpp search for "The basic types of spells" and move 3 or so lines up and alter it so it looks like this.


if(IsEffectInSpell(spell_id, SE_TemporaryPets)) //Dook- swarm pet
{
target_id = this->GetID();
}


/*
solar: The basic types of spells:


making a second post now as the next bit is huge and i think im nearing the end of this post.

Branks
09-02-2004, 05:58 AM
lovely time for the forums to crash.
so anyway still in spells.cpp now do a search for
"case SE_StackingCommand_Block:" and on the line below it and all this.


case SE_TemporaryPets: //Dook- swarms and wards
{
Mob* c=CastToClient();
Mob* targ=c->GetTarget();
if(!targ)
{
targ=c;
}
int tim=spell.unknown[12];
int time=tim*1000;
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
strcpy(npc_type->name, CastToClient()->GetName());
strcat(npc_type->name, "'s_pet");
npc_type->level = 59;
npc_type->race = 127;
npc_type->class_ = 1;
npc_type->runspeed = 1.25f;
npc_type->min_dmg = 1;
npc_type->max_dmg = 50;
npc_type->walkspeed = 0.7f;
npc_type->bodytype = 63; //Dook- claimed 63 for swarm pets
npc_type->max_hp = 100;
npc_type->cur_hp = npc_type->max_hp;
npc_type->gender = 2;
switch(spell_id) {
case 2272:
{//listed as wrath of xuzl but i dont
}//think this is in game
break;
case 3265: //3265-67 servant of ro
{
npc_type->level = 61;
npc_type->race = 89;
npc_type->texture = 2;
npc_type->max_dmg = 150;
npc_type->max_hp = 100;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
}
break;
case 3266:
{
npc_type->level = 61;
npc_type->race = 89;
npc_type->texture = 2;
npc_type->max_dmg = 150;
npc_type->max_hp = 100;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
}
break;
case 3267:
{
npc_type->level = 61;
npc_type->race = 89;
npc_type->texture = 2;
npc_type->max_dmg = 150;
npc_type->max_hp = 100;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
}
break;
case 3283: //3283-85 spirit call
{
npc_type->race = 120;
npc_type->texture = 4;
npc_type->max_hp = 2050;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
}
break;
case 3284:
{
npc_type->race = 120;
npc_type->texture = 4;
npc_type->max_hp = 2050;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
}
break;
case 3285:
{
npc_type->race = 120;
npc_type->texture = 4;
npc_type->max_hp = 2050;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npce = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()+10,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
npce->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
entity_list.AddNPC(npce);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
npce->AddToHateList(targ,1000,1000);
npce->swarm_timer->Start(time);
}
break;
case 3286: //3286-88 host of the elements
{
npc_type->race = 75;
npc_type->texture = 0;
npc_type->size = 3;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npce = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()+10,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
npce->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
entity_list.AddNPC(npce);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
npce->AddToHateList(targ,1000,1000);
npce->swarm_timer->Start(time);
}
break;
case 3287:
{
npc_type->race = 75;
npc_type->texture = 0;
npc_type->size = 3;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npce = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()+10,
c->GetZ(), c->GetHeading());
NPC* npcf = new NPC(npc_type, 0,
c->GetX()-10, c->GetY()+10,
c->GetZ(), c->GetHeading());
NPC* npcg = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()-10,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
npce->SetOwnerID(c->GetID());
npcf->SetOwnerID(c->GetID());
npcg->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
entity_list.AddNPC(npce);
entity_list.AddNPC(npcf);
entity_list.AddNPC(npcg);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
npce->AddToHateList(targ,1000,1000);
npce->swarm_timer->Start(time);
npcf->AddToHateList(targ,1000,1000);
npcf->swarm_timer->Start(time);
npcg->AddToHateList(targ,1000,1000);
npcg->swarm_timer->Start(time);
}
break;
case 3288:
{
npc_type->race = 75;
npc_type->texture = 0;
npc_type->size = 3;
if(CastToClient()->GetGM())
{
npc_type->race = 95;
npc_type->size = 3;
npc_type->gender = 2;
npc_type->texture = 0;
npc_type->max_dmg = 200;
}
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npce = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()+10,
c->GetZ(), c->GetHeading());
NPC* npcf = new NPC(npc_type, 0,
c->GetX()-10, c->GetY()+10,
c->GetZ(), c->GetHeading());
NPC* npcg = new NPC(npc_type, 0,
c->GetX()+10, c->GetY()-10,
c->GetZ(), c->GetHeading());
NPC* npch = new NPC(npc_type, 0,
c->GetX()-10, c->GetY()-10,
c->GetZ(), c->GetHeading());
NPC* npci = new NPC(npc_type, 0,
c->GetX()+8, c->GetY()+8,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
npce->SetOwnerID(c->GetID());
npcf->SetOwnerID(c->GetID());
npcg->SetOwnerID(c->GetID());
npch->SetOwnerID(c->GetID());
npci->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
entity_list.AddNPC(npce);
entity_list.AddNPC(npcf);
entity_list.AddNPC(npcg);
entity_list.AddNPC(npch);
entity_list.AddNPC(npci);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
npce->AddToHateList(targ,1000,1000);
npce->swarm_timer->Start(time);
npcf->AddToHateList(targ,1000,1000);
npcf->swarm_timer->Start(time);
npcg->AddToHateList(targ,1000,1000);
npcg->swarm_timer->Start(time);
npch->AddToHateList(targ,1000,1000);
npch->swarm_timer->Start(time);
npci->AddToHateList(targ,1000,1000);
npci->swarm_timer->Start(time);
}
break;
case 3292: //3292-94 call of xuzl
{
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->texture = 4;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
}
break;
case 3293:
{
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->texture = 4;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
}
break;
case 3294:
{
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->texture = 4;
if(CastToClient()->GetGM())
{
npc_type->race = 66;
npc_type->gender = 2;
npc_type->texture = 1;
npc_type->max_dmg = 200;
npc_type->size = 5;
}
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
NPC* npcd = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
npcd->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
entity_list.AddNPC(npcd);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
npcd->AddToHateList(targ,1000,1000);
npcd->swarm_timer->Start(time);
}
break;
case 3495:
{//another that i dont think is in game
}
break;
case 3633: //call of the mistwalker
{//some say invis man with epic, most say wolf /shrug
npc_type->race = 120;
npc_type->texture = 4;
npc_type->max_dmg = 94;
npc_type->gender = 2;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3634: //call of the dark knight
{
npc_type->equipment[7] = 145;
npc_type->max_dmg = 94;
npc_type->gender = 0;
//custom for Mog
if(CastToClient()->GetGM()) //for Mog
{
strcpy(npc_type->name, CastToClient()->GetName());
strcat(npc_type->name, "'s_Minion");
npc_type->race = 367;
npc_type->gender = 2;
npc_type->equipment[7] = 145;
npc_type->equipment[8] = 145;
npc_type->texture = 4;
npc_type->max_dmg = 1500;
npc_type->min_dmg = 500;
}
//custom for Mog
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3635: //call of faith
{ //dunno
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->max_dmg = 94;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3636: //call of battle
{ //invis war epic
npc_type->equipment[7] = 141;
npc_type->equipment[8] = 142;
npc_type->max_dmg = 94;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3637: //call of the beast
{ //wtf are the bst epic textures =/
npc_type->equipment[7] = 431;
npc_type->equipment[8] = 431;
npc_type->max_dmg = 94;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3638: //call of wu
{ //cant be right, can barely see it
npc_type->equipment[7] = 159;
npc_type->equipment[8] = 159;
npc_type->max_dmg = 94;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3639: //call of rizlona
{
npc_type->equipment[7] = 148;
npc_type->gender = 0;
npc_type->max_dmg = 94;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3640: //call of the assassin
{ //unsure on this one also
npc_type->equipment[7] = 140;
npc_type->gender = 0;
npc_type->max_dmg = 94;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3649: //call of time
{ //again no textures
//needs correct weapon
//someone said sol ro spear?
npc_type->min_dmg = 100;
npc_type->max_dmg = 415;
npc_type->equipment[7] = 431;
npc_type->equipment[8] = 431;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3807: //trickster's calling
{//not a clue what this is
npc_type->max_dmg = 90;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3869: //ancient call
{ //no clue
//needs correct weapon
npc_type->min_dmg = 100;
npc_type->max_dmg = 415;
npc_type->equipment[7] = 431;
npc_type->equipment[8] = 431;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 3870: //call of the tempest
{ //need to make this despawn when disengaged
//and limit one per fight
//without a timer
npc_type->min_dmg = 100;
npc_type->max_dmg = 330;
npc_type->race = 75;
npc_type->texture = 3;
npc_type->gender = 2;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 4460: //anguish of torment
{//again clueless
npc_type->max_dmg = 90;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 4490: //stone animation
{//......
npc_type->max_dmg = 90;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 4564: //4564-66 swarm of fear/swarm of decay
{//cant find the stonewood compound bow texture
npc_type->equipment[7] = 4;
npc_type->gender = 2;
npc_type->race = 367;
npc_type->texture = 1;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->class_ = 4;
npc_type->max_hp = 1025;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
}
break;
case 4565:
{
npc_type->equipment[7] = 4;
npc_type->gender = 2;
npc_type->race = 367;
npc_type->texture = 1;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->class_ = 4;
npc_type->max_hp = 1025;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
}
break;
case 4566:
{
npc_type->equipment[7] = 4;
npc_type->gender = 2;
npc_type->race = 367;
npc_type->texture = 1;
npc_type->walkspeed = 0;
npc_type->runspeed = 0;
npc_type->class_ = 4;
npc_type->max_hp = 1025;
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
}
break;
case 4568: //call of discord
{//no idea what this is
npc_type->max_dmg = 90;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 4569: //call of chaos
{//la la la
npc_type->max_dmg = 90;
npc_type->gender = 0;
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
npc->swarm_timer->Start(time);
}
break;
case 4790: //4790-4794=Exquisite Benediction
break;
case 4791://heard they cast aura of restoration
break;
case 4792:
break;
case 4793:
break;
case 4794:
break;
case 4796: //4796-4800=Nature's Boon
break;
case 4797:
break;
case 4798:
break;
case 4799:
break;
case 4800:
break;
case 4826: //Spirit Call 4
{//should have a 640 poison DD proc
npc_type->race = 120;
npc_type->gender = 2;
npc_type->texture = 1;
npc_type->max_hp = 2050;
npc_type->min_dmg = 80;
npc_type->max_dmg = 140;
npc_type->class_ = 91;
sprintf(npc_type->npc_attacks, "E");
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
}
break;
case 4827: //Sprit Call 5
{//should have a 640 poison DD proc
npc_type->race = 120;
npc_type->gender = 2;
npc_type->texture = 1;
npc_type->max_hp = 2050;
npc_type->min_dmg = 80;
npc_type->max_dmg = 140;
npc_type->class_ = 91;
sprintf(npc_type->npc_attacks, "E");
npc_type->cur_hp = npc_type->max_hp;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
}
break;
case 4828://Call of the Ancient 4828-4832
break;
case 4829:
break;
case 4830:
break;
case 4831:
break;
case 4832:
break;
case 4836://4836-4840 = Flaming ward of Ro
break;
case 4837:
break;
case 4838:
break;
case 4839:
break;
case 4840:
break;
case 5110: //5110-5111 wrth of xuzl
{ //Useing class 90 for their proc
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->texture = 4;
npc_type->min_dmg = 80;
npc_type->max_dmg = 140;
npc_type->class_ = 90;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
}
break;
case 5111:
{
npc_type->equipment[7] = 62;
npc_type->gender = 0;
npc_type->texture = 4;
npc_type->min_dmg = 80;
npc_type->max_dmg = 140;
npc_type->class_ = 90;
NPC* npca = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcb = new NPC(npc_type, 0,
c->GetX()-5, c->GetY()+5,
c->GetZ(), c->GetHeading());
NPC* npcc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()-5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npca->SetOwnerID(c->GetID());
npcb->SetOwnerID(c->GetID());
npcc->SetOwnerID(c->GetID());
entity_list.AddNPC(npca);
entity_list.AddNPC(npcb);
entity_list.AddNPC(npcc);
npca->AddToHateList(targ,1000,1000);
npca->swarm_timer->Start(time);
npcb->AddToHateList(targ,1000,1000);
npcb->swarm_timer->Start(time);
npcc->AddToHateList(targ,1000,1000);
npcc->swarm_timer->Start(time);
}
break;
case 5156://Call of Nexona..not a clue
break;
default:
{
c->Message(0,"Unknown pet!");
cout<<"Unknown Temporary Pet in Spell "<<spell_id<<endl;
safe_delete(npc_type);
}
}
targ->AddToHateList(c, 1, 0);
}
break;

case SE_Doppelganger:
{
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
strcpy(npc_type->name, caster->GetName());
strcat(npc_type->name, "'s_image");
npc_type->level = (caster->GetLevel());
npc_type->race = (caster->GetRace());
npc_type->class_ = (caster->GetClass());
npc_type->luclinface = caster->CastToClient()->GetFace();
npc_type->walkspeed = 0.7f;
npc_type->size = (caster->GetSize());
npc_type->runspeed = 1.25f;
npc_type->bodytype = 63;
npc_type->texture = 14;
npc_type->gender = (caster->GetGender());
npc_type->AC = (caster->GetAC());
npc_type->equipment[7] = caster->GetEquipmentMaterial(7);//primary
if(spell_id==4552)
{
npc_type->max_hp = (caster->CalcMaxHP())/2;
npc_type->min_dmg = 1;
npc_type->max_dmg = 1;
}
if(spell_id==4553)
{
npc_type->min_dmg = 1;
npc_type->max_dmg = 150;
npc_type->max_hp = (caster->CalcMaxHP());
}
if(spell_id==4554)
{
npc_type->min_dmg = 1;
npc_type->max_dmg = 150;
npc_type->max_hp = ((caster->CalcMaxHP())*1.3);
npc_type->npc_spells_id = 5;
}
npc_type->cur_hp = npc_type->max_hp;
NPC* npc = new NPC(npc_type, 0,
caster->GetX(), caster->GetY(),
caster->GetZ(), caster->GetHeading());
npc->swarm_timer->Start(600000);
safe_delete(npc_type);
entity_list.AddNPC(npc);
Mob* targ=caster->GetTarget();
if((targ)&&(targ != caster))
{
int hate=hate_list.GetEntHate(caster);
targ->AddToHateList(npc,hate+100);
npc->AddToHateList(targ,1);
}
}
break;

case SE_FadingMemories: //Dook- escape etc
{
entity_list.WipeHateAll(this);
SpellOnTarget(1406,this);
}
break;

case SE_WakeTheDead: //Dook- Wake the Dead
{
Mob* corpse=entity_list.GetMobInZoneByRange(caster, 1, 20);
Mob* c=caster;
Mob* targ=caster->GetTarget();
if(!targ)
{
targ=caster;
}
if(!corpse)
{
caster->Message(0,"Could not find the dead!");
break;
}
else
{
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
strcpy(npc_type->name, c->GetName());
strcat(npc_type->name, "'s_pet");
npc_type->level = corpse->GetLevel();
npc_type->race = corpse->GetRace();
npc_type->class_ = corpse->GetClass();
npc_type->runspeed = 1.25f;
npc_type->min_dmg = 50;
npc_type->max_dmg = 300;
npc_type->walkspeed = 0.7f;
npc_type->bodytype = 63;//Dook- useing swarm timer for this
npc_type->max_hp = 5000;
npc_type->cur_hp = npc_type->max_hp;
npc_type->gender = corpse->GetGender();
npc_type->texture = corpse->GetTexture();
npc_type->helmtexture = corpse->GetHelmTexture();
npc_type->equipment[7] = corpse->GetEquipmentMaterial(7);
npc_type->equipment[8] = corpse->GetEquipmentMaterial(8);
NPC* npc = new NPC(npc_type, 0,
c->GetX()+5, c->GetY()+5,
c->GetZ(), c->GetHeading());
safe_delete(npc_type);
npc->SetOwnerID(c->GetID());
entity_list.AddNPC(npc);
npc->AddToHateList(targ,1000,1000);
if(spell_id==3268)
npc->swarm_timer->Start(60000);
if(spell_id==3269)
npc->swarm_timer->Start(75000);
if(spell_id==3270)
npc->swarm_timer->Start(90000);
}
}
break;


well i think thats all of it but not too sure, if i find ive left anything out ill update. anyway i could really use some help finishing this up so if you see anything wrong with it please post, also i do understand theres other ways that might have been nicer or better than this but this is the current state im at, help is always appreciated and if you simply want to fill me in on some of the details im missing can do so here or on my server which ive left up basicly 24/7.

monalin crusader
09-02-2004, 10:56 AM
I havent checked your post in awhile, and so breifly skimming over it i didnt notice if you had figured out how to get aa_timers to work.
I've been working on some code to get that working right but in all my testing I cannot find any type of logic behind the aa_timer table in my db. It randomly changes when you click an aa and has nothing to do with timeing. It also does not change when a button or something is pressed. I'm still investigateing if i can find out whats going on i can let you know how i fixed the problem nearly all the code is fixed cept about one line of logic i think.

Hopefully i will find out soon i'm hopeing lay hands or harm touch will give me some clue. Even though they're not aa's theres a way that they go about triggering off. (Not really sure if that works either hehe) anyways back to codeing. Also after i get this tackled i'll start helping you with the aa's since people on my server want em working.

monalin crusader
09-02-2004, 11:30 AM
Ok after some further investigation heres what i've found. Its still not working just like i want but i'm getting closer.

The way that aa_timers is working atm is:

When the effect first goes off it sets begin < end
If you click it again it sets begin = end

it rotates in this cycle and does not go down in time.
The way i have this working now it will go off every other time

So i was looking in database::UpdateTimersClientConnected(int32 charid)

and heres what i found

if (!RunQuery(query, MakeAnyLenString(&query, "update aa_timers set end=(UNIX_TIMESTAMP(now())+(end-begin)),begin=UNIX_TIMESTAMP(now()) where charid=%i",charid), errbuf))

correct me if i'm wrong but the way they have it increases both end and begin and not only begin so no matter what they will have the same difference. Cant think of a way to fix it because i've got to go do some homework. Almost there though if u can think of a fix before i get back post it.

Draupner
09-02-2004, 11:52 AM
I had AA timers workin perfect, but I lost all the code :(

fathernitwit
09-03-2004, 03:35 AM
just to let you guys know.
I have been working with cofruben on a persistent timer which he needs for adventure stuff. The result is something which can easily be used for AAs.

Right now it automatically takes care of all the database stuff, you just use it like the current timer class, basically, and it is preserved across zones. I dont know/care how the aa_timers stuff worked, because it was kinda klumsy if you ask me.

When cofruben gets done testing it, I will hook you up with a patch that should apply to 7-31 CVS... these timers are currently in 5.8, so they will be around for sure.

monalin crusader
09-03-2004, 08:07 AM
Yeah it was set up really wird but i've figured it all out now once i do a little more work today it will be working. Got it down now where the only problem i'm having is the values it sets in aa_timers wont increase over time like it should but thats easy enough to fix i should have my source posted here by the end of today i would think.

**EDIT**

Its working now all timers for aa's should be working i will release the source when i get home from work in like 3 hours. Dont have time to do it atm.

Branks
09-03-2004, 12:18 PM
oh sweet im excited to see what you guys came up with, i kinda gave up on the current timers also since the more i looked into it the more it seems to be a simple rapid recast prevention thing than an actual timer, one of you two please say yalls system allows reenabling the button server side. currently the client does timers on its own to reenable the buttons which id like to have adjustable by the server op if possible. also monalin from what ive seen the timers in the DB arent meant to change constantly their simply there to check if current time hasnt passed the time when the timer was supposed to expire however the current system also only checks during zone changes. and fathernitwit would you mind filling me in on how much of this is broken in 5.8? im rather curious and just want a simple answer like "little different" or "omg start over" although i dont see how much of it can be broken other than actually recognizing an AA activation request, anyway thats just something ive been wondering about and one of the reasons i asked about the jr dev thing. anyway thanks again for work with the timers! guess ill spend the night playing with the monk AE attack skill as that one sounds kinda challenging.

also either of you happen to have a link to a decent code optimization tutorial or anything as i think i know enough to start working on good habbits and i still get nervous about tampering with the constantly run processes.

monalin crusader
09-03-2004, 12:42 PM
Ok finnaly heres the source code.

client_process.cpp line 5251

before // try to send all packets that weren't send before
add

database.UpdateTimersClientConnected(CharacterID() );

database.h line 124
add

bool AATimerTest(int32 charid, int32 ability);

database.cpp line 2213

after #ifdef ZONE
add

bool Database::AATimerTest(int32 charid, int32 ability){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;

if (RunQuery(query, MakeAnyLenString(&query, "SELECT begin-end from aa_timers WHERE charid=%i AND ability=%i", charid, ability), errbuf, &result)) {
while( ( row = mysql_fetch_row(result) ) ){

LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin-end=%i for ability: %i and charid: %i",atoi(row[0]),ability,charid);

if(atoi(row[0]) >= 0){
LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin <= end");
return false;
}
else{
return true;
LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin >= end");
}

}
mysql_free_result(result);
}
else
LogFile->write(EQEMuLog::Error, "Database::AATimerTest query '%s' %s", query, errbuf);

safe_delete_array(query);
}

and right before that function
where it has

void Database::UpdateTimersClientConnected(int32 charid)

change that function to

void Database::UpdateTimersClientConnected(int32 charid){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "update aa_timers set begin=UNIX_TIMESTAMP(now()) where charid=%i",charid), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query, errbuf);
}
safe_delete_array(query);
}

client.cpp line 3271

after int targ;
add

if(database.AATimerTest(CastToClient()->character_id,activate) == 0){

client.cpp line 4955 (about)

after safe_delete(outapp);
add

}
else
CastToClient()->Message(0,"You cannot cast this spell at this time.");

And i think thats about it i might have forgotten something i dont think i did let me know if it works for you guys too i've tested it on my server and it works so if it doesnt work on yours.

if(code != "works)"{
Message(1,"I probly forgot something.");
}
else if (code == "works"){
Message(1,"enjoy ");
}

and branks
also either of you happen to have a link to a decent code optimization tutorial or anything as i think i know enough to start working on good habbits and i still get nervous about tampering with the constantly run processes.

I dont know, i'm 17 and i taught myself everything i know. I believe you might be able to edit the aa timers in game by just messing with the db a little i'm not sure how it works i can look into it i hadent really thought of changing it much but i dont think it would be impossible.

**EDIT** dont emptry your aa_timers table it bugs you, also the errors you get in zone.exe mean nothign they're for me to debugg.

**EDIT** UPDATE THIS PLEASE

new AATimerTest function should be

bool Database::AATimerTest(int32 charid, int32 ability){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;

if (RunQuery(query, MakeAnyLenString(&query, "SELECT begin-end from aa_timers WHERE charid=%i AND ability=%i", charid, ability), errbuf, &result)) {
while( ( row = mysql_fetch_row(result) ) ){

LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin-end=%i for ability: %i and charid: %i",atoi(row[0]),ability,charid);

if(atoi(row[0]) >= 0){
LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin <= end");
return false;
}
else if(row[0] == "NULL"){
time_t timestamp=time(NULL);
UpdateAATimers(charid,timestamp,timestamp,ability) ;
return true;
}
else{
LogFile->write(EQEMuLog::Error, "Database::AATimerTest begin >= end");
}

}
mysql_free_result(result);
}
else{
LogFile->write(EQEMuLog::Error, "Database::AATimerTest query '%s' %s", query, errbuf);
}

safe_delete_array(query);
}

it was found to be not adding new timers under certian conditions, with the help of Branks we came up with this it solved his problem he created when he emptied his aa_timer table.

Branks
09-03-2004, 02:10 PM
worked out great! but... i was getting one of the errors from it although it was working fine so i decided maybe it didnt like the current numbers that were in the DB so i emptied my aa_timers table and then nothing worked, so it needs a function to handle if there is no table currntly there. working on this now and still trying to track down how to reenable the button when the timer expires.

edit: monalin just noticed the last part, the timers are easily changed they are set in client.cpp above and below the code you added, its the timermod which is in each case, their in seconds. and im self taught also and slowly getting better. also what i meant about the reuse thing was that id like to trackdown whatever it is thats sent to the client to let the client know the skill is avaliable, instead of the button appearing gray while its actually useable, this happens during zoneing currently but not without so its in here somewhere...

monalin crusader
09-03-2004, 02:15 PM
Oh, explain please i'm confused that shouldnt be causing problems since i just created a new character and when i did that it added the values to db just as if it had been blank. It shouldnt be causing any problems. Maybe i forgot to add something in there, did u just empty it or did u delete it, and what errors are you getting.

Oh and the errors are just in there because, u can remove them really i had that in there when i was trying to find out what the hell was going on with the aa_timers table. Those Errors really mean nothing just lets me know what was commingo ut of hte function when i would call it.

also what i meant about the reuse thing was that id like to trackdown whatever it is thats sent to the client to let the client know the skill is avaliable, instead of the button appearing gray while its actually useable, this happens during zoneing currently but not without so its in here somewhere...


They had it updateing the database only when it zoned they put the UpdateTimersClientConnected(charid) in wrong place it was only getting called on login or zone.

Branks
09-03-2004, 02:20 PM
uh it kept saying begin <= end in the zone window which i assumed it shouldnt have been so i emptied the aa_timers table and rebooted the server.

and since then it wont work im playing with it now though, it may have been some of my other code that caused this as i have a lot thats not posted im playing with.

fathernitwit
09-03-2004, 05:31 PM
alright, if your interested... heres my persistent timers:
http://eqemu.psend.com/files/ptimers.diff

apply on unix with patch -p0 <ptimers.diff from the source root.

This is basically an implementation of the Timer class, but is persistent on a per-client basis. You just have to give each timer type a unique type number... I show an example of this with AA_number... assuming that it is 0 <= AA_number <= 120... if this is not true, if there is a bigger range of AA IDs, then we can adjust the range in the header... it isnt a big deal.

heres some example code:


Client::something() {
p_timers.Start(pTimerAAStart + AA_number, duration_in_sec);

if(p_timers.Check(pTimerAAStart + AA_number, false)) {
//timer expired, use the AA
} else {
//timer not expired...
}
}

if your not in the Client:: scope, but you have a client ptr, use:
Client *c;
...
c->GetPTimers().Start(....)



heres my little writeup about them:

Persistent timers, By Father Nitwit

The idea of persistent timers is timers which follow a player
through zoning. You use operations on them much like regular
timers: Start, Check, Clear but they also provide methods
to store them in the DB: Load and Store.

Each persistent timer is attached to a character, and given
a specific type. A given character can only have one timer
of each type. While the type is just an arbitrary number,
please record what you are using it for in the enum for
pTimerType at the top of ptimer.h, and give it a UNIQUE number.

There should be little need to directly access ptimers. Each
client has a facility called p_timers which should handle
most of what you need. The idea is that instead of making
your own PersistentTimer, you use the methods on p_timers:
Start, Check, Clear, GetRemainingTime to access them. You
starting a timer which does not exist will create it. If
you need to do more than that with your timer, you should
still use p_timers, just use the Get() method to get direct
access to the PersistentTimer. All timers in the p_timers
list will automatically be loaded and stored to the database.
You should never need to call any Load or Store methods.

To get to p_timers when you are not in the Client:: scope,
use client->GetPTimers(). to access timers.

To use ptimers, you need to create the table below in your DB:

Schema:

CREATE TABLE timers (
char_id INT(11) NOT NULL,
type MEDIUMINT UNSIGNED NOT NULL,
start INT UNSIGNED NOT NULL,
duration INT UNSIGNED NOT NULL,
enable TINYINT NOT NULL,
PRIMARY KEY(char_id, type)
);

cavedude
09-04-2004, 02:08 PM
I guess this is where I should put this... Just a heads up ptimer.h and cpp weren't added to the zone's common files list in the anon CVS build that is up.