static long blow_effect(Monster_Blow.RBE effect, int atk_dam, int rlev) { /*other bad effects - minor*/ if (effect == Monster_Blow.RBE.EAT_GOLD || effect == Monster_Blow.RBE.EAT_ITEM || effect == Monster_Blow.RBE.EAT_FOOD || effect == Monster_Blow.RBE.EAT_LIGHT || effect == Monster_Blow.RBE.LOSE_CHR) { atk_dam += 5; /*other bad effects - poison / disease */ } else if (effect == Monster_Blow.RBE.POISON) { atk_dam *= 5; atk_dam /= 4; atk_dam += rlev; /*other bad effects - elements / sustains*/ } else if (effect == Monster_Blow.RBE.TERRIFY || effect == Monster_Blow.RBE.ELEC || effect == Monster_Blow.RBE.COLD || effect == Monster_Blow.RBE.FIRE) { atk_dam += 10; /*other bad effects - elements / major*/ } else if (effect == Monster_Blow.RBE.ACID || effect == Monster_Blow.RBE.BLIND || effect == Monster_Blow.RBE.CONFUSE || effect == Monster_Blow.RBE.LOSE_STR || effect == Monster_Blow.RBE.LOSE_INT || effect == Monster_Blow.RBE.LOSE_WIS || effect == Monster_Blow.RBE.LOSE_DEX || effect == Monster_Blow.RBE.HALLU) { atk_dam += 20; /*other bad effects - major*/ } else if (effect == Monster_Blow.RBE.UN_BONUS || effect == Monster_Blow.RBE.UN_POWER || effect == Monster_Blow.RBE.LOSE_CON) { atk_dam += 30; /*other bad effects - major*/ } else if (effect == Monster_Blow.RBE.PARALYZE || effect == Monster_Blow.RBE.LOSE_ALL) { atk_dam += 40; } else if ( /* Experience draining attacks */ effect == Monster_Blow.RBE.EXP_10 || effect == Monster_Blow.RBE.EXP_20) { /* change inspired by Eddie because exp is infinite */ atk_dam += 5; } else if ( effect == Monster_Blow.RBE.EXP_40 || effect == Monster_Blow.RBE.EXP_80) { /* as above */ atk_dam += 10; } /*Earthquakes*/ else if (effect == Monster_Blow.RBE.SHATTER) { atk_dam += 300; } return(atk_dam); }
static long max_dam(Monster_Race r_ptr) { int rlev, i; int melee_dam = 0, atk_dam = 0, spell_dam = 0; int dam = 1; /* Extract the monster level, force 1 for town monsters */ rlev = ((r_ptr.level >= 1) ? r_ptr.level : 1); /* Assume single resist for the elemental attacks */ spell_dam = Monster_Spell_Flag.best_spell_power(r_ptr, 1); /* Hack - Apply over 10 rounds */ spell_dam *= 10; /* Scale for frequency and availability of mana / ammo */ if (spell_dam != 0) { int freq = r_ptr.freq_spell; /* Hack -- always get 1 shot */ if (freq < 10) { freq = 10; } /* Adjust for frequency */ spell_dam = spell_dam * freq / 100; } /* Check attacks */ for (i = 0; i < 4; i++) { if (r_ptr.blow[i] == null) { continue; } /* Extract the attack infomation */ Monster_Blow.RBE effect = r_ptr.blow[i].effect; Monster_Blow.RBM method = r_ptr.blow[i].method; int d_dice = r_ptr.blow[i].d_dice; int d_side = r_ptr.blow[i].d_side; /* Hack -- no more attacks */ if (method == null) { continue; } /* Assume maximum damage*/ atk_dam = (int)blow_effect(effect, d_dice * d_side, r_ptr.level); /*stun definitely most dangerous*/ if (method == Monster_Blow.RBM.PUNCH || method == Monster_Blow.RBM.KICK || method == Monster_Blow.RBM.BUTT || method == Monster_Blow.RBM.CRUSH) { atk_dam *= 4; atk_dam /= 3; } else if (method == Monster_Blow.RBM.CLAW || method == Monster_Blow.RBM.BITE) { atk_dam *= 7; atk_dam /= 5; } /* Normal melee attack */ if (!r_ptr.flags.has(Monster_Flag.NEVER_BLOW.value)) { /* Keep a running total */ melee_dam += atk_dam; } } /* * Apply damage over 10 rounds. We assume that the monster has to make contact first. * Hack - speed has more impact on melee as has to stay in contact with player. * Hack - this is except for pass wall and kill wall monsters which can always get to the player. * Hack - use different values for huge monsters as they strike out to range 2. */ if (r_ptr.flags.test(Monster_Flag.SIZE, Monster_Flag.KILL_WALL.value, Monster_Flag.PASS_WALL.value)) { melee_dam *= 10; } else { melee_dam = melee_dam * 3 + melee_dam * Misc.extract_energy[r_ptr.speed + (r_ptr.spell_flags.has(Monster_Spell_Flag.HASTE.value) ? 5 : 0)] / 7; } /* * Scale based on attack accuracy. We make a massive number of assumptions here and just use monster level. */ melee_dam = melee_dam * Math.Min(45 + rlev * 3, 95) / 100; /* Hack -- Monsters that multiply ignore the following reductions */ if (!r_ptr.flags.has(Monster_Flag.MULTIPLY.value)) { /*Reduce damamge potential for monsters that move randomly */ if (r_ptr.flags.test(Monster_Flag.SIZE, Monster_Flag.RAND_25.value, Monster_Flag.RAND_50.value)) { int reduce = 100; if (r_ptr.flags.has(Monster_Flag.RAND_25.value)) { reduce -= 25; } if (r_ptr.flags.has(Monster_Flag.RAND_50.value)) { reduce -= 50; } /*even moving randomly one in 8 times will hit the player*/ reduce += (100 - reduce) / 8; /* adjust the melee damage*/ melee_dam = (melee_dam * reduce) / 100; } /*monsters who can't move aren't nearly as much of a combat threat*/ if (r_ptr.flags.has(Monster_Flag.NEVER_MOVE.value)) { if (r_ptr.spell_flags.has(Monster_Spell_Flag.TELE_TO.value) || r_ptr.spell_flags.has(Monster_Spell_Flag.BLINK.value)) { /* Scale for frequency */ melee_dam = melee_dam / 5 + 4 * melee_dam * r_ptr.freq_spell / 500; /* Incorporate spell failure chance */ if (!r_ptr.flags.has(Monster_Flag.STUPID.value)) { melee_dam = melee_dam / 5 + 4 * melee_dam * Math.Min(75 + (rlev + 3) / 4, 100) / 500; } } else if (r_ptr.flags.has(Monster_Flag.INVISIBLE.value)) { melee_dam /= 3; } else { melee_dam /= 5; } } } /* But keep at a minimum */ if (melee_dam < 1) { melee_dam = 1; } /* * Combine spell and melee damage */ dam = (spell_dam + melee_dam); r_ptr.highest_threat = (short)dam; r_ptr.spell_dam = spell_dam; /*AMF:DEBUG*/ r_ptr.melee_dam = melee_dam; /*AMF:DEBUG*/ /* * Adjust for speed. Monster at speed 120 will do double damage, * monster at speed 100 will do half, etc. Bonus for monsters who can haste self. */ dam = (dam * Misc.extract_energy[r_ptr.speed + (r_ptr.spell_flags.has(Monster_Spell_Flag.HASTE.value) ? 5 : 0)]) / 10; /* * Adjust threat for speed -- multipliers are more threatening. */ if (r_ptr.flags.has(Monster_Flag.MULTIPLY.value)) { r_ptr.highest_threat = (short)((r_ptr.highest_threat * Misc.extract_energy[r_ptr.speed + (r_ptr.spell_flags.has(Monster_Spell_Flag.HASTE.value) ? 5 : 0)]) / 5); } /* * Adjust threat for friends. */ if (r_ptr.flags.has(Monster_Flag.FRIENDS.value)) { r_ptr.highest_threat *= 2; } else if (r_ptr.flags.has(Monster_Flag.FRIEND.value)) { r_ptr.highest_threat = (short)(r_ptr.highest_threat * 3 / 2); } /*but deep in a minimum*/ if (dam < 1) { dam = 1; } /* We're done */ return(dam); }