/*
This daemon is used to modify shifter time and other things.
Its hidden away to obscure exactly how long things are and what
they mean because some wizards with global read cant be trusted.
*/
#include "/d/Shifters/shifter.h"
#define KILLS 0
#define LEARNING 1
#define MAXMOD 2
#define KILLWEIGHT 3
#define LEARNWEIGHT 4
#define LEARNVAL 0
#define LWEIGHT 1
mapping modifier;
mapping learn;
// assume 100xp/kill for low
// assume 400xp/kill for mid
void create() {
modifier = ([ "opossum" : 100; 0; 25; 100; 0,
"frog" : 400; (["frog_corpse": 350; 100 ]); 25; 80; 20,
"flower" : 0; (["healing" : 6300 ; 100]); 25; 0 ; 100,
"tree" : 800; ([ "tree_berry" : 100; 50, "tree_poison" : 200; 50, "tree_thorns" : 200; 0 ]) ; 25; 80; 20,
"treant" : 1500; (["entangle" : 1500 ; 100]); 25; 50; 50,
"chameleon" : 400; (["hide" : 1000; 25, "cham_corpse" : 400; 75]); 25; 50; 50,
"nelitos" : 1000; (["nelitos_bite" : 1000; 70, "nelitos_corpse" : 500 ; 30 ]); 25; 50; 50,
"drakon" : 2000; (["tail" : 6000; 50, "breath" : 2000 ; 50]); 25; 50; 50,
"rock" : 0; ([ "rolling" : 2000; 100 ]); 25; 0; 100,
ROCK2 : 800; (["throwing" : 1500; 100 , "repelling" : 100; 0, "catching" : 100; 0 ]); 25; 50; 50,
ROCK3 : 2000; (["mweapon" : 2500; 40, "marmour" : 2000; 40, "spike" : 1000; 20 ]); 25; 50; 50,
"cat" : 400; (["cat_corpse" : 400; 100 ]); 25; 80; 20,
"panther" : 1000; (["panther_bite" : 1500; 70, "panther_corpse" : 500; 30 ]); 25; 50; 50,
"xaerre" : 2000; (["claw" : 2500; 100 ]); 25; 50; 50,
]);
learn = ([ "hide" : 30000 ,
"healing" : 20000,
"entangle" : 5000,
"tree_berry" : 500,
"tree_poison" : 5000,
"tree_thorns" : 5000,
"cham_corpse" : 1000,
"nelitos_bite" : 3000,
"nelitos_corpse" : 2000,
"tail" : 10000,
"breath" : 8000,
"rolling" : 2000,
"throwing" : 10000,
"mweapon" : 10000,
"marmour" : 10000,
"spike" : 10000,
"repelling" : 5000,
"catching" : 5000,
"cat_corpse" : 1000,
"frog_corpse" : 1000,
"panther_bite" : 3000,
"panther_corpse" : 2000,
"claw" : 8000,
]);
}
int check_previous() {
if (geteuid(previous_object()) != "Shifters" &&
geteuid(previous_object()) != "paldin" &&
geteuid(previous_object()) != "serf") return 0;
return 1;
}
mapping mods() {
if (!check_previous()) return 0;
return modifier;
}
mapping learn() {
if (!check_previous()) return 0;
return learn;
}
int duration_mod(string type, int duration, int base_dur, mapping learning, mapping kills) {
mapping m_val;
string *idx;
int i;
int val;
int mod;
int dur;
if (!check_previous()) return 0;
// Basic 20% extra time before we remove potential time
dur = duration/5;
// Added to duration to make it swing more!
duration += dur;
// How much to modify for randomisation (+/- 10%)
// Also add to duration so bonuses below help
dur += duration*(10-base_dur)/100;
duration += dur;
if (!kills) kills = ([ ]);
if (!learning) learning = ([ ]);
// Kills
val = kills[type];
if (val && modifier[type,KILLS]) {
if (val > modifier[type,KILLS])
val = modifier[type,KILLS];
// Mod being % to modify diration.
mod = val*modifier[type,MAXMOD]*modifier[type,KILLWEIGHT]/(100*modifier[type,KILLS]);
dur -= mod*duration/100;
}
// Learning Mod
m_val = modifier[type,LEARNING];
if (m_val) {
idx = m_indices(m_val);
for(i=0;i<sizeof(idx);i++) {
if (val = learning[idx[i]]) {
if (val > modifier[type,LEARNING][idx[i],LEARNVAL])
val = modifier[type,LEARNING][idx[i],LEARNVAL];
mod = ( (val*modifier[type,LEARNING][idx[i],LWEIGHT]) / (modifier[type,LEARNING][idx[i],LEARNVAL]) ) *
modifier[type,MAXMOD] * modifier[type,LEARNWEIGHT] / (10000);
dur -= mod*duration/100;
}
}
}
return dur;
}
int exp_mod(string type, int exp, int base_xp, mapping learning, mapping kills) {
int xp;
if (!check_previous()) return 0;
// How much to modify for randomisation (+/- 10%)
xp = exp*(10-base_xp)/100;
return xp;
}
int query_learn_calc(string ability,int bonus, int mod) {
if (!check_previous()) return 0;
return learn[ability]*mod*bonus+
bonus*bonus*mod*(learn[ability]/(250))*(learn[ability]/(250));
}
int query_learning_mod(string ability, int mod, int abi) {
int ret;
int i,calc,calc2;
if (!check_previous()) return 0;
if (!mod) mod = 2; // Shouldnt happen but dont want divide by 0
ret = 0;
if (learn[ability] && abi > learn[ability]) {
// Ok I couldnt think of how to calculate this easily, so did a loop check
for(i=11;i>0;i--) {
calc = query_learn_calc(ability,i,mod);
if (abi > calc) return i;
}
}
return ret;
}
int damage_function(string type, object per, int size, string form, string abi, int max, int mod, int bonus) {
object co;
int learn;
int level;
int tmp;
int ldiff;
if (!check_previous()) return 0;
if (!mod) mod = 1;
level = (per->query_level()>MAXMORTAL?MAXMORTAL:per->query_level());
ldiff = (level-WIZALLOW>0?level-WIZALLOW:0);
if (per && (co = CLASSOB(per)) )
learn = co->query_learning_modifier(form,abi,max)/mod;
switch (type) {
case "opossum_pouch_weight" : return (12+size+TIMEBONUS(per,form,10)/2)*bonus/10;
case "opossum_reverse_weight" : return (10*bonus/(12+size+TIMEBONUS(per,form,10)/2));
case "frog_healing" : return (bonus+TIMEBONUS(per,form,10)+learn);
case ROCK2+"_shard" : return 4+random(6+learn);
case ROCK2+"_fire_bon" : return learn;
case ROCK2+"_fire_small" : return 1+random(4+learn);
case ROCK2+"_fire_def" : return 1+random(12+learn);
case ROCK2+"_fire_med" : return 5+random(4+learn);
case ROCK2+"_fire_large" : return 9+random(4+learn);
case ROCK2+"_throw_balls" : return 4+random(16+learn);
case ROCK2+"_throw_mud" : return 4+random(5+learn);
case ROCK2+"_repel_targ" : return random(per->query_str()/3+bonus+6);
case ROCK2+"_repel_me" : return random(per->query_str()/4+3*bonus+learn);
case ROCK2+"_catch_targ" : return random(per->query_str()/4+bonus+5);
case ROCK2+"_catch_me" : return random(per->query_str()/4+3*bonus+learn);
case ROCK3+"_weap" : return ldiff/3+(random(3)<ldiff%3?1:0);
case ROCK3+"_armour" : return level/4+size*3;
// bonus = dam, size = hp reduction. Clip dam to half hp, to max at 1.5 bonus
case ROCK3+"_spike" : return 16*size/10+learn+ldiff+(bonus*2>size?size/2:bonus);
case "cat_healing" : return bonus+TIMEBONUS(per,form,5)+random(learn);
case "panther_bite" : return 5+size+random(level/2 + learn);
case "panther_corpse" : return bonus+TIMEBONUS(per,form,10)+random(learn);
case "xaerre_claw" : return random(level) + 5*size + random(3*ldiff)+learn;
case "flower_healing_bonus" : return TIMEBONUS(per,form,10)/2+learn;
case "flower_healing" : return size/3+random((2*size+2+bonus)/2);
case "flower_healing_full" : return random(5);
case "tree_rain": return 1+random(TIMEBONUS(per,form,10)/2);
case "treant_entangle_chance" : return random(learn+2*size+bonus+level/2);
case "treant_entangle_chance_targ" : return random(3*per->query_dex()/2);
case "treant_entangle_hit_mod" : return -size;
case "treant_entangle_hit_bonus" : return -size -ldiff/4;
case "treant_entangle_prim_att" : return 2*size + random(20+learn);
case "treant_entangle_break" : return random(3*per->query_str()/2);
case "treant_entangle_break_me" : return random(level+per->query_str()+3*size+learn);
case "chameleon_corpse" : return bonus+learn;
case "nelitos_bite_chance" : return size+3+random(learn);
case "nelitos_bite" : return 5+size+random(level/2+learn);
case "nelitos_corpse" : return bonus+TIMEBONUS(per,form,10)+random(learn);
case "drakon_tail": return size+random(size);
case "drakon_tail2" : return size + 2 + random(2*size + 2 + learn);
case "drakon_mystical" : return level*3/4 + size*4 + random(2*level+learn);
case "drakon_fire" : return (level / 2) + size + random(level+2*size+learn);
case "drakon_cold" : return (level/2) + size + random(level+learn);
}
}
int ua_wc(string type, int brawl, int size, object per) {
int ldiff;
if (!check_previous()) return 0;
switch(type) {
case "opossum" : return (1 + size - brawl);
case "frog" : return (2+size - brawl);
case "frog_insect" : return (3*(1+size) - brawl);
case ROCK2 : return (6 - brawl + 2*size);
case ROCK2+"_nohp" : return (6 - brawl + size);
case ROCK3 : return (6 - brawl + size/2);
case "cat" : return (2+size - brawl);
case "panther" : return (8+size - brawl);
case "xaerre" : if (!per->query_wielded_weapon() &&
!per->query_second_weapon()) {
ldiff = per->query_level()-WIZALLOW;
ldiff = (ldiff>30?30:ldiff);
if (ldiff > 0) return (8+size - brawl - brawl/4 + random(brawl+1) +ldiff/4);
return (8+size - brawl - brawl/4 + random(brawl+1) );
}
return 0; // for weapons
case "tree" : return (12+size/2 - brawl);
case "treant" : return (size*2 + 9 - brawl);
case "chameleon_insect" : return (3*(2+size) - brawl);
case "chameleon" : return (2+size - brawl );
case "nelitos" : return (5+2*size - brawl);
// Remove brawl .. then add back brawl/4 - brawl/8 av. ie 1/8 brawl
case "drakon" : return (9+size - brawl - brawl/8 + random((brawl+1)/2));
}
}
int hit_ac(string typename, int dam, int targ, string type, object per,int size) {
int ldiff;
int x;
if (!check_previous()) return 0;
x = dam;
switch(typename) {
case "opossum" : return -random(size);
case "frog" : return -random(3+size/2);
case ROCK2+"_same" : return -3*dam/4;
case ROCK2+"_1_pierce" : return -(1+random(6));
case ROCK2+"_1_chop" : return -(1+random(4));
case ROCK2+"_1" : return -(random(4));
case ROCK2+"_2_pierce" : return -(1+random(8));
case ROCK2+"_2_slash" : return -(1+random(6));
case ROCK2+"_2" : return -(1+random(4));
case ROCK2+"_3_crush" : return -(random(4));
case ROCK2+"_3_elec" : return -dam/2;
case ROCK2+"_3" : return -(1+random(5));
case ROCK2+"_4_repel" : return -(2+random(6));
case ROCK2+"_4" : return -(1+random(6));
case ROCK2+"_4_catch" : return dam/5;
case ROCK2+"_5_cold" : return dam/2;
case ROCK2+"_5_fire" : return -dam/3;
case ROCK2+"_5" : return -(1+random(8));
case ROCK2 : return -(2+random(2*size));
case "cat" : return -random(3+size/2);
case "panther" : return -(random(5+size/2));
case "xaerre" : return -(random(2+size));
case "tree" : if (type == "fire") dam = 3*dam/2;
if (type == "chop") dam = 3*dam/2;
return (-x+dam-random(8+size));
case "treant" : if (type == "fire") dam = 4*dam/3;
if (type == "chop") dam = 4*dam/3;
ldiff = per->query_level()-WIZALLOW;
ldiff = ldiff>30?30:ldiff;
if (ldiff > 0)
return (-x+dam-random(9+size+ldiff/3)-size+1);
return (-x+dam-random(9+size)-size+1);
case "chameleon" : return -(random(2+size));
case "nelitos" : return -(random(7+size/2));
case "drakon" : return -(random(5+size));
}
}
int tohit_ac(string type,int size, int w, object per) {
object rm;
if (!check_previous()) return 0;
if (per) rm = environment(per);
switch(type) {
case "opossum" : return random(size);
case "frog" : return random(3+size/2);
case ROCK2: return 0;
case "cat" : return random(3+size/2);
case "panther" : return random(3+size/2);
case "xaerre" : return random(2+3*size/2);
case "tree" : return random(size);
case "treant" : if (rm && rm->query_outdoorness() >= 3) return -3*size;
return random(12+size/2);
case "chameleon" : return random(2+size);
case "nelitos" : return random(5+size/2);
case "drakon" : return random(4+size);
}
}
int mimeon_max_wc(string weapon_type, status twohanded) {
if (!check_previous()) return 0;
switch (weapon_type) {
case "Axe" : if (twohanded) return 17;
return 16;
case "Club" : if (twohanded) return 19;
return 14;
case "Curved Blade" : return 17;
case "Flail" : return 17;
case "Knife" : return 13;
case "Longsword" : return 18;
case "Polearm" : return 19;
case "Rapier" : return 15;
case "Shortsword" : return 15;
case "Spear" : return 15;
case "Staff" : if (twohanded) return 15;
return 10;
case "Two Handed Axe" : return 19;
case "Two Handed Sword" : return 19;
}
return 15;
}
int query_maxtime_modifier(string form,int max_time,int formtime ,int maxmod) {
int mod;
if (!max_time) max_time = 1;
mod = (formtime-max_time)/max_time;
if (mod > maxmod && maxmod) mod=maxmod;
if (mod < 0) mod = 0; // should only happen on wizards
return mod;
}