/* * $Header: /HexenWorld/Siege/stats.hc 26 6/01/98 2:49a Mgummelt $ */ float ExperienceValues[66] = { // Paladin 945, // Level 2 - spot 0 2240, // Level 3 5250, // Level 4 10150, // Level 5 21000, // Level 6 39900, // Level 7 72800, // Level 8 120400, // Level 9 154000, // Level 10 210000, // Level 11 - spot + 9 210000, // Required amount for each level afterwards // Crusader 911, // Level 2 - spot 11 2160, // Level 3 5062, // Level 4 9787, // Level 5 20250, // Level 6 38475, // Level 7 70200, // Level 8 116100, // Level 9 148500, // Level 10 202500, // Level 11 - spot + 9 202500, // Required amount for each level afterwards // Necromancer 823, // Level 2 - spot 22 1952, // Level 3 4575, // Level 4 8845, // Level 5 18300, // Level 6 34770, // Level 7 63440, // Level 8 104920, // Level 9 134200, // Level 10 183000, // Level 11 - spot + 9 183000, // Required amount for each level afterwards // Assassin 675, // Level 2 - spot 33 1600, // Level 3 3750, // Level 4 7250, // Level 5 15000, // Level 6 28500, // Level 7 52000, // Level 8 86000, // Level 9 110000, // Level 10 150000, // Level 11 - spot + 9 150000, // Required amount for each level afterwards // Succubus 871, // Level 2 - spot 44 2060, // Level 3 4822, // Level 4 9319, // Level 5 19278, // Level 6 36626, // Level 7 66804, // Level 8 110494, // Level 9 141334, // Level 10 192700, // Level 11 - spot + 9 192700, // Required amount for each level afterwards // Dwarf 945, 2240, 5250, 10150, 21000, 39900, 72800, 120400, 154000, 210000, 210000 }; // min health, max health, // min health per level up to level 10, min health per level up to level 10, // health per level past level 10 /* float hitpoint_table[25] = { 70, 85, // Paladin 8, 13, 4, 65, 75, // Crusader 5, 10, 3, 65, 75, // Necromancer 5, 10, 3, 65, 75, // Assassin 5, 10, 3, 65, 75, // Succubus 5, 10, 3, 90, 100, // Dwarf 10, 15, 5 }; */ float mana_table[30] = { // Startup Per Level Past // min max min max 10th Level 0, 0, 0, 0, 0, // Paladin 100, 100, 0, 0, 0, // Crusader 100, 200, 10, 12, 4, // Necromancer 0, 0, 0, 0, 0, // Assassin 100, 100, 0, 0, 0, // Succubus 0, 0, 0, 0, 0 // Dwarf }; float strength_table[12] = { 17, 21, // Paladin 11, 14, // Crusader 6, 10, // Necromancer 10, 13, // Assassin 12, 15, // Succubus 15, 20 // Dwarf }; float intelligence_table[12] = { 6, 10, // Paladin 10, 13, // Crusader 15, 18, // Necromancer 6, 10, // Assassin 9, 13, // Succubus 8, 14 // Dwarf }; float wisdom_table[12] = { 6, 10, // Paladin 15, 18, // Crusader 10, 13, // Necromancer 12, 15, // Assassin 11, 14, // Succubus 14, 18 // Dwarf }; float dexterity_table[12] = { 10, 13, // Paladin 6, 10, // Crusader 8, 12, // Necromancer 15, 18, // Assassin 9, 13, // Succubus 8, 12 // Dwarf }; void PlayerSpeed_Calc (entity who) { if(who.beast_time>time) { who.hasted = 1.666; return; } switch (who.playerclass) { case CLASS_ASSASSIN: who.hasted=1; break; case CLASS_SUCCUBUS: who.hasted=.95; break; case CLASS_PALADIN: who.hasted=.9; break; case CLASS_CRUSADER: who.hasted=.85; break; case CLASS_NECROMANCER: who.hasted=.8; break; case CLASS_DWARF: who.hasted=1; break; } if (who.artifact_active & ART_HASTE) who.hasted *= 2.5; else if(who.flags2&FL2_EXCALIBUR) who.hasted *=1.8; if (who.hull==HULL_CROUCH) // Player crouched { if(who.playerclass!=CLASS_DWARF) who.hasted *= .6; else { if(who.super_damage) who.hasted *= (.7 + who.super_damage/10); else who.hasted *= .7; } if(who.sheep_time>time) who.hasted *= 2;//sheep were too slow } if (who.flags2&FL2_POISONED) // Player poisoned who.hasted *= .8; if(who.puzzle_inv1==g_keyname)//key carrier a bit slower who.hasted *= .75; // if(who.waterlevel==3)//swimming mod // who.hasted*=player_swim_mod[who.playerclass - 1]; } /* float CLASS_PALADIN = 1; float CLASS_CRUSADER = 2; float CLASS_NECROMANCER = 3; float CLASS_ASSASSIN = 4; float CLASS_SUCCUBUS = 5; */ // Make sure we get a real distribution beteen // min-max, otherwise, max will only get choosen when // random() returns 1.0 float stats_compute(float min, float max) { float value; value = (max-min+1)*random() + min; if (value > max) value = max; value = ceil(value); return value; } void stats_NewPlayer(entity e) { float index; // Stats already set? if (e.strength) return; if (e.playerclass < CLASS_PALADIN || e.playerclass > CLASS_DWARF) { sprint(e,PRINT_MEDIUM, "Invalid player class "); sprint(e,PRINT_MEDIUM, ftos(e.playerclass)); sprint(e,PRINT_MEDIUM, "\n"); return; } // Calc initial health index = (e.playerclass - 1) * 5; e.health = stats_compute(hitpoint_table[index], hitpoint_table[index+1]); e.max_health = e.health; // Calc initial mana index = (e.playerclass - 1) * 5; e.max_mana = stats_compute(mana_table[index], mana_table[index+1]); index = (e.playerclass - 1) * 2; e.strength = stats_compute(strength_table[index], strength_table[index+1]); e.intelligence = stats_compute(intelligence_table[index], intelligence_table[index+1]); e.wisdom = stats_compute(wisdom_table[index], wisdom_table[index+1]); e.dexterity = stats_compute(dexterity_table[index], dexterity_table[index+1]); e.level = 1; e.experience = 0; } // Jump ahead one level void player_level_cheat() { float index; index = (self.playerclass - 1) * (MAX_LEVELS+1); if (self.level > MAX_LEVELS) index += MAX_LEVELS - 1; else index += self.level - 1; self.experience = ExperienceValues[index]; if (self.level > MAX_LEVELS) self.experience += (self.level - MAX_LEVELS) * ExperienceValues[index+1]; PlayerAdvanceLevel(self.level+1); } void player_experience_cheat(void) { // AwardExperience(self,self,350); return; } /* ================ PlayerAdvanceLevel This routine is called (from the game C side) when a player is advanced a level (self.level) ================ */ void PlayerAdvanceLevel(float NewLevel) { string s2; float OldLevel,Diff; float index,HealthInc,ManaInc; sound (self, CHAN_VOICE, "misc/comm.wav", 1, ATTN_NONE); OldLevel = self.level; self.level = NewLevel; Diff = self.level - OldLevel; if(!Diff) { return; } sprint(self,PRINT_MEDIUM, "You are now level "); s2 = ftos(self.level); sprint(self,PRINT_MEDIUM, s2); sprint(self,PRINT_MEDIUM, "!\n"); if(!self.newclass) { /* if (self.playerclass == CLASS_PALADIN) { sprint(self,PRINT_MEDIUM, "Paladin gained a level\n"); } else if (self.playerclass == CLASS_CRUSADER) { sprint(self,PRINT_MEDIUM, "Crusader gained a level\n"); // Special ability #1, full mana at level advancement self.bluemana = self.greenmana = self.max_mana; } else if (self.playerclass == CLASS_NECROMANCER) { sprint(self,PRINT_MEDIUM, "Necromancer gained a level\n"); } else if (self.playerclass == CLASS_ASSASSIN) { sprint(self,PRINT_MEDIUM, "Assassin gained a level\n"); } else if (self.playerclass == CLASS_SUCCUBUS) { sprint(self,PRINT_MEDIUM,"Demoness gained a level\n"); } */ switch (self.playerclass) { case CLASS_DWARF: centerprint(self, "Dwarf gained a level\n"); break; case CLASS_PALADIN: centerprint(self, "Paladin gained a level\n"); break; case CLASS_CRUSADER: centerprint(self,"Crusader gained a level\n"); // Special ability #1, full mana at level advancement //self.bluemana = self.greenmana = self.max_mana; break; case CLASS_NECROMANCER: centerprint(self,"Necromancer gained a level\n"); break; case CLASS_ASSASSIN: centerprint(self,"Assassin gained a level\n"); break; case CLASS_SUCCUBUS: centerprint(self,"Demoness gained a level\n"); break; } } if (self.playerclass < CLASS_PALADIN || self.playerclass > MAX_CLASS) return; index = (self.playerclass - 1) * 5; // Have to do it this way in case they go up more than 1 level at a time while(Diff > 0) { OldLevel += 1; Diff -= 1; if (OldLevel <= MAX_LEVELS) { HealthInc = stats_compute(hitpoint_table[index+2],hitpoint_table[index+3]); ManaInc = stats_compute(mana_table[index+2],mana_table[index+3]); } else { HealthInc = hitpoint_table[index+4]; ManaInc = mana_table[index+4]; } self.health += HealthInc; self.max_health += HealthInc; // An upper limit of 150 on health if (self.health > 150) self.health = 150; if (self.max_health > 150) self.max_health = 150; // self.greenmana += ManaInc; // self.bluemana += ManaInc; self.max_mana += ManaInc; if(!deathmatch) { sprint(self, PRINT_LOW,"Stats: MP +"); s2 = ftos(ManaInc); sprint(self, PRINT_LOW, s2); sprint(self, PRINT_LOW, " HP +"); s2 = ftos(HealthInc); sprint(self, PRINT_LOW, s2); sprint(self, PRINT_LOW, "\n"); } } if (self.level > 2) self.flags(+)FL_SPECIAL_ABILITY1; if (self.level >5) self.flags(+)FL_SPECIAL_ABILITY2; } float FindLevel(entity WhichPlayer) { float Chart; float Amount,Position,Level; if (WhichPlayer.playerclass < CLASS_PALADIN || WhichPlayer.playerclass > MAX_CLASS) return WhichPlayer.level; Chart = (WhichPlayer.playerclass - 1) * (MAX_LEVELS+1); //paladin : 0 //crusader: 11 //necro : 22 //assassin: 33 //succubus: 44 Level = 0; Position=0; while(Position < MAX_LEVELS && Level == 0) { if (WhichPlayer.experience < ExperienceValues[Chart+Position]) Level = Position+1; Position += 1; } if (!Level) { Amount = WhichPlayer.experience - ExperienceValues[Chart + MAX_LEVELS - 1]; Level = ceil(Amount / ExperienceValues[Chart + MAX_LEVELS]) + MAX_LEVELS; } return Level; } void AwardExperience(entity ToEnt, entity FromEnt, float Amount) { float AfterLevel; float IsPlayer; entity SaveSelf; float index,test40,test80,diff,index2,totalnext,wis_mod; if (!Amount) return; if(ToEnt.deadflag>=DEAD_DYING) return; IsPlayer = (ToEnt.classname == "player"); if (!IsPlayer) { return; } if (FromEnt != world && Amount == 0.0) { Amount = FromEnt.experience_value; } if (ToEnt.level <4) Amount *= .5; if (ToEnt.playerclass == CLASS_PALADIN) Amount *= 1.4; else if (ToEnt.playerclass == CLASS_CRUSADER) Amount *= 1.35; else if (ToEnt.playerclass == CLASS_NECROMANCER) Amount *= 1.22; wis_mod = ToEnt.wisdom - 11; Amount+=Amount*wis_mod/20;//from .75 to 1.35 if(ToEnt.experience+Amount>2500000)//Cap exp at 2.5 million, @ level 20 return; ToEnt.experience += Amount; if (IsPlayer) { AfterLevel = FindLevel(ToEnt); // dprintf("Total Experience: %s\n",ToEnt.experience); if(AfterLevel>20) AfterLevel = 20; if (ToEnt.level != AfterLevel) { SaveSelf = self; self = ToEnt; PlayerAdvanceLevel(AfterLevel); self = SaveSelf; } } // Crusader Special Ability #1: award full health at 40% and 80% of levels experience if (IsPlayer) { if (ToEnt.playerclass == CLASS_CRUSADER) { index = (ToEnt.playerclass - 1) * (MAX_LEVELS+1); if ((ToEnt.level - 1) > MAX_LEVELS) index += MAX_LEVELS; else index += ToEnt.level - 1; if (ToEnt.level == 1) { test40 = ExperienceValues[index] * .4; test80 = ExperienceValues[index] * .8; } else if ((ToEnt.level - 1) <= MAX_LEVELS) { index2 = index - 1; diff = ExperienceValues[index] - ExperienceValues[index2]; test40 = ExperienceValues[index2] + (diff * .4); test80 = ExperienceValues[index2] + (diff * .8); } else // Past MAX_LEVELS { totalnext = ExperienceValues[index - 1]; // index is 1 past MAXLEVEL at this point totalnext += ((ToEnt.level - 1) - MAX_LEVELS) * ExperienceValues[index]; test40 = totalnext + (ExperienceValues[index] * .4); test80 = totalnext + (ExperienceValues[index] * .8); } if (((ToEnt.experience - Amount) < test40) && (ToEnt.experience> test40)) ToEnt.health = ToEnt.max_health; else if (((ToEnt.experience - Amount) < test80) && (ToEnt.experience> test80)) ToEnt.health = ToEnt.max_health; } } } /* ====================================== void stats_NewClass(entity e) MG Used when doing a quick changeclass ====================================== */ void stats_NewClass(entity e) { entity oself; float index,newlevel; if (e.playerclass < CLASS_PALADIN || e.playerclass > MAX_CLASS) { sprint(e,PRINT_MEDIUM, "Invalid player class "); sprint(e,PRINT_MEDIUM, ftos(e.playerclass)); sprint(e,PRINT_MEDIUM, "\n"); return; } // Calc initial health index = (e.playerclass - 1) * 5; e.health = stats_compute(hitpoint_table[index], hitpoint_table[index+1]); e.max_health = e.health; // Calc initial mana index = (e.playerclass - 1) * 5; e.max_mana = stats_compute(mana_table[index], mana_table[index+1]); index = (e.playerclass - 1) * 2; e.strength = stats_compute(strength_table[index], strength_table[index+1]); e.intelligence = stats_compute(intelligence_table[index], intelligence_table[index+1]); e.wisdom = stats_compute(wisdom_table[index], wisdom_table[index+1]); e.dexterity = stats_compute(dexterity_table[index], dexterity_table[index+1]); //Add level diff stuff if(dmMode==DM_SIEGE) newlevel = 6; else newlevel = FindLevel(e); e.level=1; if(newlevel>1) { oself=self; self=e; PlayerAdvanceLevel(newlevel); self=oself; } } /* ====================================== drop_level MG Used in deathmatch where you don't lose all exp, just enough to drop you down one level. ====================================== */ void drop_level (entity loser,float number) { float pos,lev_pos,new_exp,mana_dec,health_dec,dec_pos; //string printnum; if(fixedLevel) { return; } if(loser.classname!="player") return; /* sprint(loser,PRINT_HIGH,"Dropping "); sprint(loser,PRINT_HIGH,loser.netname); sprint(loser,PRINT_HIGH," "); printnum = ftos(number); sprint(loser,PRINT_HIGH,printnum); sprint(loser,PRINT_HIGH," levels from L"); printnum=ftos(loser.level); sprint(loser,PRINT_HIGH,printnum); sprint(loser,PRINT_HIGH," to L"); if(loser.level - number < 1) { sprint(loser,PRINT_HIGH,"1"); } else { printnum=ftos(loser.level-number); sprint(loser,PRINT_HIGH,printnum); } sprint(loser,PRINT_HIGH,"!\n"); */ if(loser.level-number<1) {//would drop below level 1, set to level 1 loser.experience=0; dec_pos = (loser.playerclass - 1) * 5; loser.max_health= hitpoint_table[dec_pos]; loser.max_mana = mana_table[dec_pos]; if(loser.health>loser.max_health) loser.health=loser.max_health; if(loser.bluemana>loser.max_mana) loser.bluemana=loser.max_mana; if(loser.greenmana>loser.max_mana) loser.greenmana=loser.max_mana; return; } pos = (loser.playerclass - 1) * (MAX_LEVELS+1); if(loser.level-number>1) { loser.level-=number; lev_pos+=loser.level - 2; if(lev_pos>9)//last number in that char's { new_exp=ExperienceValues[pos+10]; loser.experience=new_exp+new_exp*(lev_pos - 9); } else loser.experience = ExperienceValues[pos+lev_pos]; } else { loser.level=1; loser.experience=0; } if (loser.level <= 2) loser.flags(-)FL_SPECIAL_ABILITY1; if (loser.level <=5) loser.flags(-)FL_SPECIAL_ABILITY2; dec_pos = (loser.playerclass - 1) * 5; health_dec = hitpoint_table[dec_pos+4]; mana_dec = mana_table[dec_pos+4]; loser.max_health -= health_dec *number; if(loser.health>loser.max_health) loser.health=loser.max_health; loser.max_mana -= mana_dec *number; if(loser.bluemana>loser.max_mana) loser.bluemana=loser.max_mana; if(loser.greenmana>loser.max_mana) loser.greenmana=loser.max_mana; }