Lots of monster stuff, particularly documenting monster abilities
- Monster radiate abilities can now specify a spell pattern to use - Fix some abilities being incorrectly shown in the editor's ability details dialog (for example, radiate abilities were shown as "Summon aid") - Add the recently-added monster missile types to the options offered in the editor - Fix chance of activating not being editable for the martyr's shield ability - Show the monster summoned for summoning abilities (finally!) - Show the subcategory for unusual abilities (one of active, passive death) - Fix the displayed percentage chance for summon abilities (the permille was shown instead) - Fix incorrect action point display in the editor for the two recently-added monster missiles - Fix crash when editing a missile ability - Fix abilities page not showing the newly-added or recently-edited ability after exiting the detail/option dialog - Fix pick monster button for summoning abilities being off by one
This commit is contained in:
@@ -39,6 +39,14 @@ contains slots 0 to 9 (numbered left to right), the second row contains slots 11
|
||||
and so on. Each sheet contains 100 slots; thus, slots 0 to 99 are on sheet 0, slots 100 to
|
||||
199 or on sheet 1, and so forth.</p>
|
||||
|
||||
<p>If you don't like having to do the calculations to figure out which graphic is in which
|
||||
slot, select Classify Custom Graphics from the Scenario menu, and go through your custom
|
||||
graphics, telling the editor what purpose each one is intended for. If you want to use a
|
||||
single graphic for multiple purposes (eg, an item and a monster), you'll still have to
|
||||
occasionally calculate a graphic number, but by classifying them here, they'll
|
||||
automatically show up in all the usual Choose Graphic lists, after all the preset
|
||||
graphics.</p>
|
||||
|
||||
<h2>How to Make Your Custom Sheets</h2>
|
||||
|
||||
<p>Make your graphic in a painting program, and save it as 8-bit PNG (both indexed and RGB
|
||||
|
@@ -141,6 +141,8 @@ aren't immune to fire.</li>
|
||||
node as its action, which can do anything a special node can do. This can be used to
|
||||
create special abilities that are otherwise not supported - for example, you could use
|
||||
this to make a monster that can teleport.</li>
|
||||
<li><b>Special when hit (Advanced) -</b> When you hit the monster with a weapon, a special
|
||||
node is called.</li>
|
||||
<li><b>Death Triggers Scenario Special (Advanced) -</b> The extra value is the number of a
|
||||
scenario special node, which is called when a creature of this type is killed.</li>
|
||||
<li><b>Custom Ability (Advanced) -</b> Most of the abilities listed above are pre-made
|
||||
|
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 7 - Special Encounter Examples</h1>
|
||||
<h1>Appendix 8 - Special Encounter Examples</h1>
|
||||
|
||||
<p>Extra examples can be very useful when making special encounters. Here are a few quick
|
||||
sets of instructions for making popular types of encounters.</p>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 2 - Item Ability Types</h1>
|
||||
<h1>Appendix 3 - Item Ability Types</h1>
|
||||
|
||||
<p>Each item type can have a special ability. The types of abilities available range from
|
||||
shooting fireballs to weapons doing special damage to dragons to items being ingredients
|
||||
|
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 6 - Spell and Alchemy Lists</h1>
|
||||
<h1>Appendix 7 - Spell and Alchemy Lists</h1>
|
||||
|
||||
<p>You can set special encounter nodes to give the party mage spells, priest spells, and
|
||||
alchemical recipes. These lists contains the numbers you enter to give specific
|
||||
|
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 5 - Text Messages</h1>
|
||||
<h1>Appendix 6 - Text Messages</h1>
|
||||
|
||||
<p>You can edit the text messages for the scenario, a town, or an outdoor section. This
|
||||
gives you the chance to directly edit the adventure text, without going through the
|
||||
|
216
doc/editor/appendix/Monsters.html
Normal file
216
doc/editor/appendix/Monsters.html
Normal file
@@ -0,0 +1,216 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<script src='../nav.js' type='application/javascript'></script>
|
||||
<noscript>Javascript required for the navbar.</noscript>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 5 - Monster Abilities</h1>
|
||||
|
||||
<p>When adding a new monster ability, you may have noticed that there are fourteen custom
|
||||
options to choose from at the end of the list. These options don't fill in the ability
|
||||
parameters with a template; they just present you immediately with the full ability
|
||||
dialog. You can also get there by editing an existing ability.</p>
|
||||
<p>This appendix covers all the options you can get in the ability editing dialog.</p>
|
||||
<p>Note: If you add a custom ability and want to cancel it, you have to click Delete,
|
||||
rather than Cancel. Clicking Cancel will cause the ability to be added with default values
|
||||
(generally all zeroes).</p>
|
||||
|
||||
<h2>The Basics</h2>
|
||||
|
||||
<p>When editing any monster ability, you'll see four informational fields.</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Monster</b> - This is here to remind you what the monster is you're editing an
|
||||
ability for.</li<
|
||||
<li><b>Display name</b> - Shows the ability's name as it will be shown in-game, for
|
||||
example when casting Scry Monster.</li>
|
||||
<li><b>Ability Type</b> - The type of ability. This was set when you added the ability and
|
||||
cannot be changed. (If you want to change it, you'll have to add a new ability and delete
|
||||
the old one.)</li>
|
||||
<li><b>Action Points</b> - Shows the number of action points the ability consumes when the
|
||||
monster activates it. This is usually based on the type and subtype, but sometimes you can
|
||||
set it directly.</li>
|
||||
<li><b>Subtype</b> - Most abilities allow you to choose a subtype. Click Choose to select
|
||||
from a list. The options depend on the ability type.</li>
|
||||
<li><b>Delete</b> - You can delete the ability by clicking this button.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Missile Abilities</h2>
|
||||
|
||||
<p>Monsters will not use most missile abilities when adjacent to their target. Missile
|
||||
abilities offer the following "subtypes":</p>
|
||||
|
||||
<ul>
|
||||
<li>Darts</li>
|
||||
<li>Bow and Arrows</li>
|
||||
<li>Spears</li>
|
||||
<li>Rocks or Stones</li>
|
||||
<li>Razordisks</li>
|
||||
<li>Spines - can be used while adjacent</li>
|
||||
<li>Knives</li>
|
||||
<li>Crossbow and Bolts</li>
|
||||
<li>Rocks or Boulders - uses an extra action point compared to stones</li>
|
||||
<li>Rapid Bow and Arrows - uses one less action point than regular bow</li>
|
||||
</ul>
|
||||
|
||||
<p>In addition, you can set the following properties:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Missile Graphic</b> - Click Choose to select your missile graphic from the
|
||||
list.</li>
|
||||
<li><b>Dice, Sides</b> - This works the same as the monster's regular attacks.</li>
|
||||
<li><b>Range</b> - The maximum range at which the ability can function, in tiles.</li>
|
||||
<li><b>Chance</b> - The per mille chance (ie, out of 1000) that the monster chooses to use
|
||||
this ability.</li>
|
||||
<li><b>Skill</b> - This is similar to the monster's skill level, affecting their chance of
|
||||
hitting.</li>
|
||||
</ul>
|
||||
|
||||
<h2>General Abilities</h2>
|
||||
|
||||
<p>General abilities cover several categories with a variety of effects. Some of these are
|
||||
obvious, others less so. Even when ranged, monsters will also use most of these abilities
|
||||
while adjacent to their target. The following is a list of all ability types classified as
|
||||
general, using the terminology from the Add Ability page:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Damage</b> - Deals direct damage. Ability strength indicates the number of dice;
|
||||
the number of sides is determined by the subtype (ray/gaze - d6, breath - d8, touch/spit -
|
||||
d10).</li>
|
||||
<li><b>Damage (full attack)</b> - Like damage, but takes 4 action points when used as a
|
||||
breath weapon ability. If used as a touch attack, it's identical to damage. You get this
|
||||
type by selecting a simple breath weapon (fire, ice, electricity, or darkness).</li>
|
||||
<li><b>Status Effect</b> - Afflicts the target with some status effect. Ability strength
|
||||
is the amount inflicted.</li>
|
||||
<li><b>Field</b> - Places fields around the target. Ability strength indicates the size of
|
||||
the affected area; press Choose to select one. Note that the open square will not damage
|
||||
the target itself.</li>
|
||||
<li><b>Petrification</b> - Turns target to stone. Ability strength affects the chance of
|
||||
resisting.</li>
|
||||
<li><b>SP drain</b> - Drains spell points. Ability strength is the percentage of spell
|
||||
points drained.</li>
|
||||
<li><b>XP drain</b> - Drains experience. Draining experience does not affect your level,
|
||||
but you'll need to regain the experience before you can gain a level. Ability strength is
|
||||
the amount drained.</li>
|
||||
<li><b>Death</b> - Kills the target by dealing a very large amount of damage. Ability
|
||||
strength indicates the number of d10's to roll (it's multiplied by 10, so a strength of 1
|
||||
means 10d10).</li>
|
||||
<li><b>Steal food/gold</b> - Drains your food or gold. Ability strength is the maximum
|
||||
amount to drain (a random number less than or equal is taken).</li>
|
||||
<li><b>Undead stat</b> - This is similar to status effect, but is also negated by the
|
||||
life-saving item ability.</li>
|
||||
<li><b>Weapon stat</b> - This is the same as status effect, except when used as a touch
|
||||
attack. In that case, it can only occur on attack 1, never on attacks 2 or 3. You could
|
||||
use this for a beast with a disease-ridden bite or an assassin with a poisoned blade.</li>
|
||||
</ul>
|
||||
|
||||
<p>They offer the following "subtypes":</p>
|
||||
|
||||
<ul>
|
||||
<li>Ray
|
||||
<li>Touch - no range, occurs as part of normal melee attack</li>
|
||||
<li>Gaze
|
||||
<li>Breath
|
||||
<li>Spit - can't be used while adjacent</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that a non-ranged attack could be made using Ray, Gaze, or Breath simply by
|
||||
limiting the range to 1, but this still differs from a Touch attack because the latter
|
||||
accompanies the plain damage of the monster's regular attack.</p>
|
||||
|
||||
<p>In addition, you can set the following properties:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Missile Graphic</b> - Click Choose to select your missile graphic from the
|
||||
list.</li>
|
||||
<li><b>Range</b> - The maximum range at which the ability can function, in tiles.</li>
|
||||
<li><b>Chance</b> - The per mille chance (ie, out of 1000) that the monster chooses to use
|
||||
this ability.</li>
|
||||
<li><b>Strength</b> - This determines how powerful the ability is. Its exact effect
|
||||
depends on the ability type.</li>
|
||||
<li><b>Damage, Status, or Field Type</b> - Additional information for some ability types;
|
||||
the meaning is obvious. Click Choose to select one from a list.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Radiate Field Abilities</h2>
|
||||
|
||||
<p>Monsters that radiate fields are automatically immune to their own fields. Since
|
||||
radiate abilities are passive, they take no action points. A radiate ability provides no
|
||||
subtypes; the only editable parameters are as follows:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Field Type</b> - The type of field to radiate. You can pick anything, but keep in
|
||||
mind that when the radiation is activated, an area centred on the creature is filled with
|
||||
fields, so generally something like barriers or forcecages is a poor choice.</li>
|
||||
<li><b>Radiate Chance</b> - The percent chance each turn of the ability activating.</li>
|
||||
<li><b>Affected Area</b> - The area to effect. Click Choose to select one.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Summoning Abilities</h2>
|
||||
|
||||
<p>Since summon abilities are passive, they take no action points to activate. They do
|
||||
have the following subtypes:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Specific</b> - Always summons a specific type of creature that you choose.</li>
|
||||
<li><b>Strength</b> - Summons a creature based on its summon strength, just like the
|
||||
general summoning spells.</li>
|
||||
<li><b>Race</b> - Summons a creature based on its race. This form can potentially result
|
||||
in wildly different levels, so use it with caution.</li>
|
||||
</ul>
|
||||
|
||||
<p>You can specify the following parameters for a summoning ability:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Monster, race, etc</b> - Specify what sort of creature to summon by clicking the
|
||||
Choose button.</li>
|
||||
<li><b>Max, min</b> - The number of monsters summoned will be a random number in this
|
||||
range.</li>
|
||||
<li><b>Duration</b> - You can specify how long the summoned monsters will remain.</li>
|
||||
<li><b>Chance</b> - The percent chance each turn of summoning.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Other Abilities</h2>
|
||||
|
||||
<p>There are several other abilities that can be added to monsters. They don't have a
|
||||
dedicated "Custom Ability" option, but you can edit them after adding for some increased
|
||||
customization. (The special node abilities assume you'll want to do this and automatically
|
||||
open the edit window once you've saved the node.)</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Splits when hit</b> - You can specify the per mille chance of the monster splitting
|
||||
each time it is hit.</li>
|
||||
<li><b>Permanent martyr's shield</b> - You can specify the per mille chance of the
|
||||
martyr's shield activating each time the monster is hit.</li>
|
||||
<li><b>Absorb spells</b> - You can specify the per mille chance of spells being absorbed
|
||||
each time the monster is subject to them. Normally, the monster gains health proportional
|
||||
to the damage that would have been dealt; however, some non-damaging effects can also be
|
||||
absorbed, and in that case the monster gains a fixed amount of health that you specify
|
||||
here.</li>
|
||||
<li><b>Shoots webs</b> - This is a legacy support type, but you can nevertheless specify
|
||||
the range of the ability and the per mille chance of the monster deciding to use it. It
|
||||
differs from a general field ability in that the monster will use it even if adjacent to
|
||||
the target.</li>
|
||||
<li><b>Heat ray</b> - This is a legacy support type, but you can nevertheless specify the
|
||||
range, strength (in number of d6's), and per mille chance of the monster deciding to use
|
||||
it. It differs from a standard damage ray in that it costs only one action point. It does
|
||||
not allow you to customize the damage type; it always deals fire damage.</li>
|
||||
<li><b>Special action</b> - This calls a special node as part of the monster's action. You
|
||||
can specify how many action points it costs as well as the per mille chance of the monster
|
||||
deciding to use it. Of course, from here you can also edit the special node that is
|
||||
called.</li>
|
||||
<li><b>Death/hit special</b> - This calls a special node when the monster dies or when it
|
||||
is hit. It does not have any options (other than specifying which node to call). Of
|
||||
course, from here you can edit the special node that is called.</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 4 - Blades Sound Effects</h1>
|
||||
<h1>Appendix 5 - Blades Sound Effects</h1>
|
||||
|
||||
<p>There are several places in the editor where you are asked for the number of a sound
|
||||
effect. These are the available Blades effects:</p>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h2>Section 14: Appendix 1 - Special Encounter Node Types</h2>
|
||||
<h2>Appendix 1 - Special Encounter Node Types</h2>
|
||||
|
||||
<p>These are the many types of special encounter nodes. They are divided into six
|
||||
different categories, and given with examples and descriptions of what the various editing
|
||||
|
@@ -11,11 +11,11 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
<h1>Appendix 3 - Starting Terrain Types</h1>
|
||||
<h1>Appendix 4 - Starting Terrain Types</h1>
|
||||
|
||||
<p>There are 256 premade terrain types (numbered 0 - 255) in the basic scenario you start
|
||||
with. Many of them have special properties, or need to be handled in different ways.
|
||||
Remember that terrain types 0-90 cant be edited (except for the graphic).</p>
|
||||
This appendix also notes which terrain types are used by the default combat arenas.</p>
|
||||
|
||||
<ul>
|
||||
<li>Type 0,1 - Cave Floors (2 types)</li>
|
||||
@@ -91,6 +91,36 @@ terrain type, after the special is triggered the white spot will disappear.</li>
|
||||
different cardinal directions.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Combat Arenas</h2>
|
||||
|
||||
<ol start='0'>
|
||||
<li>Grassy field - uses terrain types 2, 3, 4, 112, 114, 115, sometimes 83</li>
|
||||
<li>Ordinary cave - uses terrain types 0, 1, 93, 94, 95, 98, sometimes 82</li>
|
||||
<li>Mountain - uses terrain types 36, 37, sometimes 83</li>
|
||||
<li>Surface bridge - uses terrain types 50, 63, 64, 83</li>
|
||||
<li>Cave bridge - uses terrain types 71, 74, 82</li>
|
||||
<li>Rubble-strewn cave - uses terrain types 0, 84, 92, 95, 97, 98, sometimes 82</li>
|
||||
<li>Cave forest - uses terrain types 0, 91, 92, 93, 95, 98, sometimes 82</li>
|
||||
<li>Cave mushrooms - uses terrain types 0, 1, 92, 93, 94, 95, sometimes 82</li>
|
||||
<li>Cave swamp - uses terrain types 0, 1, 92, 95, 96, 112, sometimes 82</li>
|
||||
<li>Surface rocks - uses terrain types 2, 3, 87, 110, 113, 114, sometimes 83</li>
|
||||
<li>Surface swamp - uses terrain types 2, 3, 4, 111, sometimes 83</li>
|
||||
<li>Surface woods - uses terrain types 2, 3, 4, 112, 113, 114, sometimes 83</li>
|
||||
<li>Surface shrubbery - uses terrain types 2, 3, 4, 112, 114, 115, sometimes 83</li>
|
||||
<li>Stalagmites - uses terrain types 0, 1, 75, 76, 97, 98, sometimes 82</li>
|
||||
<li>Cave fumarole - uses terrain types 0, 1, 75, 76, 94, 98</li>
|
||||
<li>Surface fumarole - uses terrain types 36, 37, 75, 76</li>
|
||||
<li>Cave camp - uses terrain types 0, 1, 92, 93, 94, 95, 98, 104, 105</li>
|
||||
<li>Surface camp - uses terrain types 2, 3, 4, 104, 105, 112, 114, 115</li>
|
||||
<!-- Note: In the above, 104 and 105 will be replaced, as they are the bedding and campfire. -->
|
||||
<li>Cave crops - uses terrain types 0, 1, 84, 93, 97, 98,
|
||||
plus the terrain type the arena was triggered from</li>
|
||||
<li>Surface crops - uses terrain types 2, 3, 4, 87, 110,
|
||||
plus the terrain type the arena was triggered from</li>
|
||||
</ol>
|
||||
|
||||
<p>In addition to the above, the walls (5-35) are used to make edges around the map and occasionally pillars in the middle.</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -24,6 +24,7 @@ document.write('\
|
||||
<ol style="list-style-type:upper-alpha">\
|
||||
<li><a href="appendix/Specials.html">Special Encounter Node Types</a></li>\
|
||||
<li><a href="appendix/Items.html">Item Ability Types</a></li>\
|
||||
<li><a href="appendix/Monsters.html">Monster Ability Types</a></li>\
|
||||
<li><a href="appendix/Terrain.html">Starting Terrain Types</a></li>\
|
||||
<li><a href="appendix/Sounds.html">Blades Sound Effects</a></li>\
|
||||
<li><a href="appendix/Messages.html">Text Messages</a></li>\
|
||||
|
@@ -17,6 +17,10 @@
|
||||
<text top='164' left='10' width='120' height='16'>Radiate Chance:</text>
|
||||
<field name='odds' top='162' left='120' width='50' height='16'/>
|
||||
|
||||
<text top='192' left='10' width='100' height='16'>Area Affected:</text>
|
||||
<field name='pat' top='190' left='120' width='50' height='16'/>
|
||||
<button name='pick-pat' type='regular' top='187' left='180'>Choose</button>
|
||||
|
||||
<button name='okay' type='regular' top='216' left='330'>OK</button>
|
||||
<button name='cancel' type='regular' def-key='esc' top='216' left='265'>Cancel</button>
|
||||
<button name='delete' type='regular' top='216' left='10'>Delete</button>
|
||||
|
@@ -96,6 +96,7 @@ Absorb spells
|
||||
Web missile
|
||||
Heat ray (costs 1 action point)
|
||||
Call special node
|
||||
Call special when hit
|
||||
Death triggers special
|
||||
Radiate fields
|
||||
Summon aid
|
||||
@@ -106,17 +107,16 @@ Summon aid
|
||||
|
||||
|
||||
|
||||
|
||||
Darts
|
||||
Bow/Arrows
|
||||
Spears
|
||||
Rocks
|
||||
Rocks/Stones
|
||||
Razordisks
|
||||
Spines
|
||||
Knives
|
||||
Crossbow/Bolts
|
||||
|
||||
|
||||
Rocks/Boulders
|
||||
Bow/Arrows (Rapid)
|
||||
Ray
|
||||
Touch
|
||||
Gaze
|
||||
@@ -160,7 +160,7 @@ Summon random creature of species
|
||||
Chance of Activating
|
||||
|
||||
|
||||
|
||||
Chance of Activating
|
||||
|
||||
|
||||
Chance of Activating
|
||||
|
@@ -2545,8 +2545,35 @@ void do_monster_turn() {
|
||||
|
||||
// Place fields for monsters that create them. Only done when monst sees foe
|
||||
if(target != 6 && can_see_light(cur_monst->cur_loc,targ_space,sight_obscurity) < 5) {
|
||||
if(cur_monst->abil[eMonstAbil::RADIATE].active && get_ran(1,1,100) < cur_monst->abil[eMonstAbil::RADIATE].radiate.chance)
|
||||
place_spell_pattern(square, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
if(cur_monst->abil[eMonstAbil::RADIATE].active && get_ran(1,1,100) < cur_monst->abil[eMonstAbil::RADIATE].radiate.chance) {
|
||||
switch(cur_monst->abil[eMonstAbil::RADIATE].radiate.pat) {
|
||||
case PAT_SINGLE:
|
||||
place_spell_pattern(single, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_SMSQ:
|
||||
place_spell_pattern(small_square, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_SQ:
|
||||
place_spell_pattern(square, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_OPENSQ:
|
||||
place_spell_pattern(open_square, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_RAD2:
|
||||
place_spell_pattern(radius2, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_RAD3:
|
||||
place_spell_pattern(radius3, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_PLUS:
|
||||
place_spell_pattern(t, cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
case PAT_WALL:
|
||||
int dir = (cur_monst->direction + 6) % 8;
|
||||
place_spell_pattern(field[dir], cur_monst->cur_loc, cur_monst->abil[eMonstAbil::RADIATE].radiate.type, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cur_monst->abil[eMonstAbil::SUMMON].active && get_ran(1,1,100) < cur_monst->abil[eMonstAbil::SUMMON].summon.chance) {
|
||||
uAbility abil = cur_monst->abil[eMonstAbil::SUMMON];
|
||||
mon_num_t what_summon = 0;
|
||||
|
@@ -356,7 +356,10 @@ static void put_monst_info(cDialog& me, const cCreature& store_m) {
|
||||
if(i > 4) break; // TODO: Support showing more than just the first four abilities
|
||||
if(!abil.second.active) continue;
|
||||
std::string id = "abil" + std::to_string(i);
|
||||
me[id].setText(abil.second.to_string(abil.first));
|
||||
std::string name = abil.second.to_string(abil.first);
|
||||
if(abil.first == eMonstAbil::SUMMON && abil.second.summon.type == eMonstSummon::TYPE)
|
||||
name.replace(name.find("%s"), 2, univ.scenario.scen_monsters[abil.second.summon.what].m_name);
|
||||
me[id].setText(name);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "oldstructs.h"
|
||||
@@ -305,28 +306,28 @@ std::map<eMonstAbil,uAbility>::iterator cMonster::addAbil(eMonstAbilTemplate wha
|
||||
return abil.find(eMonstAbil::DEATH_TRIGGER);
|
||||
// Radiate abilities
|
||||
case eMonstAbilTemplate::RADIATE_FIRE:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_FIRE, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_FIRE, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_ICE:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_ICE, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_ICE, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_SHOCK:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_FORCE, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_FORCE, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_ANTIMAGIC:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::FIELD_ANTIMAGIC, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::FIELD_ANTIMAGIC, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_SLEEP:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::CLOUD_SLEEP, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::CLOUD_SLEEP, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_STINK:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::CLOUD_STINK, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::CLOUD_STINK, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_BLADE:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_BLADES, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::WALL_BLADES, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
case eMonstAbilTemplate::RADIATE_WEB:
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::FIELD_WEB, param};
|
||||
abil[eMonstAbil::RADIATE].radiate = {true, eFieldType::FIELD_WEB, param, PAT_SQ};
|
||||
return abil.find(eMonstAbil::RADIATE);
|
||||
// Advanced abilities
|
||||
case eMonstAbilTemplate::CUSTOM_MISSILE:
|
||||
@@ -772,7 +773,7 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
case eMonstAbil::DRAIN_XP: sout << "Draining"; break;
|
||||
case eMonstAbil::KILL: sout << "Death"; break;
|
||||
case eMonstAbil::STEAL_FOOD: sout << "Steals food"; break;
|
||||
case eMonstAbil::STEAL_GOLD: sout << "Steals gold!"; break;
|
||||
case eMonstAbil::STEAL_GOLD: sout << "Steals gold"; break;
|
||||
case eMonstAbil::FIELD:
|
||||
switch(gen.fld) {
|
||||
case eFieldType::SPECIAL_EXPLORED:
|
||||
@@ -878,7 +879,7 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
case eMonstAbilCat::SPECIAL:
|
||||
switch(key) {
|
||||
case eMonstAbil::SPLITS:
|
||||
sout << "Splits when hit (" << special.extra1 << "% chance)";
|
||||
sout << "Splits when hit (" << std::fixed << std::setprecision(1) << double(special.extra1) / 10 << "% chance)";
|
||||
break;
|
||||
case eMonstAbil::MARTYRS_SHIELD:
|
||||
sout << "Permanent martyr's shield";
|
||||
@@ -893,9 +894,13 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
sout << "Heat ray (" << special.extra3 << "d6)";
|
||||
break;
|
||||
case eMonstAbil::SPECIAL:
|
||||
sout << "Unusual ability (active)";
|
||||
break;
|
||||
case eMonstAbil::DEATH_TRIGGER:
|
||||
sout << "Unusual ability (death)";
|
||||
break;
|
||||
case eMonstAbil::HIT_TRIGGER:
|
||||
sout << "Unusual ability";
|
||||
sout << "Unusual ability (passive)";
|
||||
break;
|
||||
// Non-special abilities
|
||||
case eMonstAbil::STUN: case eMonstAbil::NO_ABIL: case eMonstAbil::RADIATE: case eMonstAbil::SUMMON:
|
||||
@@ -906,8 +911,49 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
}
|
||||
break;
|
||||
case eMonstAbilCat::SUMMON:
|
||||
// TODO: Somehow look up the name of the monster to be summoned
|
||||
sout << "Summons " << summon.min << '-' << summon.max << ' ' << "monst-name" << "s (" << summon.chance << "% chance)";
|
||||
sout << "Summons " << summon.min << '-' << summon.max << ' ';
|
||||
switch(summon.type) {
|
||||
case eMonstSummon::TYPE:
|
||||
sout << "%s";
|
||||
break;
|
||||
case eMonstSummon::SPECIES:
|
||||
switch(eRace(summon.what)) {
|
||||
case eRace::BEAST: sout << "beasts"; break;
|
||||
case eRace::BIRD: sout << "birds"; break;
|
||||
case eRace::BUG: sout << "bugs"; break;
|
||||
case eRace::DEMON: sout << "demons"; break;
|
||||
case eRace::DRAGON: sout << "dragons"; break;
|
||||
case eRace::GIANT: sout << "giants"; break;
|
||||
case eRace::GOBLIN: sout << "goblins"; break;
|
||||
case eRace::HUMAN: sout << "humans"; break;
|
||||
case eRace::HUMANOID: sout << "humanoids"; break;
|
||||
case eRace::IMPORTANT: sout << "VIPs"; break;
|
||||
case eRace::MAGE: sout << "mages"; break;
|
||||
case eRace::MAGICAL: sout << "magical beings"; break;
|
||||
case eRace::NEPHIL: sout << "nephilim"; break;
|
||||
case eRace::PLANT: sout << "plants"; break;
|
||||
case eRace::PRIEST: sout << "priests"; break;
|
||||
case eRace::REPTILE: sout << "reptiles"; break;
|
||||
case eRace::SKELETAL: sout << "skeletal undead"; break;
|
||||
case eRace::SLIME: sout << "slimes"; break;
|
||||
case eRace::SLITH: sout << "sliths"; break;
|
||||
case eRace::STONE: sout << "mineral beings"; break;
|
||||
case eRace::UNDEAD: sout << "undead"; break;
|
||||
case eRace::UNKNOWN: sout << "monsters"; break;
|
||||
case eRace::VAHNATAI: sout << "vahnatai"; break;
|
||||
}
|
||||
break;
|
||||
case eMonstSummon::LEVEL:
|
||||
switch(summon.what) {
|
||||
case 0: sout << "cannon fodder"; break;
|
||||
case 1: sout << "minor allies"; break;
|
||||
case 2: sout << "allies"; break;
|
||||
case 3: sout << "major allies"; break;
|
||||
case 4: sout << "protectors"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sout << " (" << summon.chance << "% chance)";
|
||||
break;
|
||||
case eMonstAbilCat::RADIATE:
|
||||
sout << "Radiates ";
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "simpletypes.h"
|
||||
#include "graphtool.hpp"
|
||||
#include "living.hpp"
|
||||
#include "spell.hpp"
|
||||
|
||||
namespace legacy {
|
||||
struct monster_record_type;
|
||||
@@ -90,6 +91,7 @@ union uAbility {
|
||||
bool active;
|
||||
eFieldType type;
|
||||
int chance;
|
||||
eSpellPat pat;
|
||||
} radiate;
|
||||
struct {
|
||||
bool active;
|
||||
|
@@ -874,7 +874,10 @@ static void put_monst_abils_in_dlog(cDialog& me, cMonster& monst) {
|
||||
me["abil-edit" + id].setText("Add");
|
||||
}
|
||||
} else if(i % 4 == 3) abils.addPage();
|
||||
me["abil-name" + id].setText(abil.second.to_string(abil.first));
|
||||
std::string name = abil.second.to_string(abil.first);
|
||||
if(abil.first == eMonstAbil::SUMMON && abil.second.summon.type == eMonstSummon::TYPE)
|
||||
name.replace(name.find("%s"), 2, scenario.scen_monsters[abil.second.summon.what].m_name);
|
||||
me["abil-name" + id].setText(name);
|
||||
me["abil-edit" + id].setText("Edit");
|
||||
i++;
|
||||
}
|
||||
@@ -963,12 +966,15 @@ static short get_monst_abil_num(std::string prompt, int min, int max, cDialog& p
|
||||
static void fill_monst_abil_detail(cDialog& me, cMonster& monst, eMonstAbil abil, uAbility detail) {
|
||||
eMonstAbilCat cat = getMonstAbilCategory(abil);
|
||||
me["monst"].setText(monst.m_name);
|
||||
std::string name = detail.to_string(abil);
|
||||
if(abil == eMonstAbil::SUMMON && detail.summon.type == eMonstSummon::TYPE)
|
||||
name.replace(name.find("%s"), 2, scenario.scen_monsters[detail.summon.what].m_name);
|
||||
me["name"].setText(detail.to_string(abil));
|
||||
// These names start at line 80 in the strings file, but the first valid ability is ID 1, so add 79.
|
||||
me["type"].setText(get_str("monster-abilities", 79 + int(abil)));
|
||||
// Action points
|
||||
if(cat == eMonstAbilCat::MISSILE) {
|
||||
if(detail.missile.type == eMonstMissile::ARROW || detail.missile.type == eMonstMissile::BOLT || detail.missile.type == eMonstMissile::SPINE || detail.missile.type == eMonstMissile::RAPID_ARROW)
|
||||
if(detail.missile.type == eMonstMissile::ARROW || detail.missile.type == eMonstMissile::BOLT || detail.missile.type == eMonstMissile::SPINE || detail.missile.type == eMonstMissile::BOULDER)
|
||||
me["ap"].setTextToNum(3);
|
||||
else me["ap"].setTextToNum(2);
|
||||
} else if(cat == eMonstAbilCat::GENERAL) {
|
||||
@@ -1005,9 +1011,11 @@ static void fill_monst_abil_detail(cDialog& me, cMonster& monst, eMonstAbil abil
|
||||
me["missile"].show();
|
||||
me["pick-missile"].show();
|
||||
me["missile-pic"].show();
|
||||
me["missile-touch"].hide();
|
||||
if(cat != eMonstAbilCat::MISSILE)
|
||||
me["missile-touch"].hide();
|
||||
me["range"].show();
|
||||
me["range-touch"].hide();
|
||||
if(cat != eMonstAbilCat::MISSILE)
|
||||
me["range-touch"].hide();
|
||||
}
|
||||
miss_num_t missile;
|
||||
int range;
|
||||
@@ -1036,6 +1044,8 @@ static void fill_monst_abil_detail(cDialog& me, cMonster& monst, eMonstAbil abil
|
||||
if(abil == eMonstAbil::FIELD)
|
||||
me["extra"].setTextToNum(int(detail.gen.fld));
|
||||
else me["field"].setTextToNum(int(detail.radiate.type));
|
||||
if(cat == eMonstAbilCat::RADIATE)
|
||||
me["pat"].setTextToNum(int(detail.radiate.pat));
|
||||
}
|
||||
// Other type-specific fields
|
||||
if(cat == eMonstAbilCat::MISSILE) {
|
||||
@@ -1101,6 +1111,7 @@ static void save_monst_abil_detail(cDialog& me, eMonstAbil abil, uAbility& detai
|
||||
detail.summon.chance = me["odds"].getTextAsNum();
|
||||
} else if(cat == eMonstAbilCat::RADIATE) {
|
||||
detail.radiate.chance = me["odds"].getTextAsNum();
|
||||
detail.radiate.pat = eSpellPat(me["pat"].getTextAsNum());
|
||||
} else if(cat == eMonstAbilCat::SPECIAL) {
|
||||
detail.special.extra1 = me["extra1"].getTextAsNum();
|
||||
detail.special.extra2 = me["extra2"].getTextAsNum();
|
||||
@@ -1167,10 +1178,10 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
|
||||
return true;
|
||||
}
|
||||
}
|
||||
size_t iShow = std::distance(monst.abil.begin(), iter);
|
||||
dynamic_cast<cStack&>(me["abils"]).setPage(iShow / 4);
|
||||
if(tmpl < eMonstAbilTemplate::CUSTOM_MISSILE && tmpl != eMonstAbilTemplate::SPECIAL) {
|
||||
put_monst_abils_in_dlog(me, monst);
|
||||
size_t iShow = std::distance(monst.abil.begin(), iter);
|
||||
dynamic_cast<cStack&>(me["abils"]).setPage(iShow / 4);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@@ -1211,7 +1222,7 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
|
||||
|
||||
if(cat == eMonstAbilCat::MISSILE || cat == eMonstAbilCat::GENERAL || cat == eMonstAbilCat::SUMMON) {
|
||||
int first, last;
|
||||
if(cat == eMonstAbilCat::MISSILE) first = 110, last = 117;
|
||||
if(cat == eMonstAbilCat::MISSILE) first = 110, last = 119;
|
||||
else if(cat == eMonstAbilCat::GENERAL) first = 120, last = 124;
|
||||
else if(cat == eMonstAbilCat::SUMMON) first = 150, last = 152;
|
||||
abil_dlg["pick-subtype"].attachClickHandler([&,cat,first,last](cDialog& me,std::string,eKeyMod) -> bool {
|
||||
@@ -1270,17 +1281,26 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
|
||||
fill_monst_abil_detail(me, monst, abil, abil_params);
|
||||
return true;
|
||||
});
|
||||
abil_dlg["pick-pat"].attachClickHandler([&](cDialog& me,std::string,eKeyMod) -> bool {
|
||||
save_monst_abil_detail(me, abil, abil_params);
|
||||
int i = abil_params.radiate.pat;
|
||||
i = choose_text(STRT_SPELL_PAT, i, &me, "Which spell pattern?");
|
||||
abil_params.radiate.pat = eSpellPat(i);
|
||||
fill_monst_abil_detail(me, monst, abil, abil_params);
|
||||
return true;
|
||||
});
|
||||
} else if(cat == eMonstAbilCat::SUMMON) {
|
||||
abil_dlg["pick-summon"].attachClickHandler([&](cDialog& me,std::string,eKeyMod) -> bool {
|
||||
save_monst_abil_detail(me, abil, abil_params);
|
||||
int i = abil_params.summon.what;
|
||||
eStrType type;
|
||||
switch(abil_params.summon.type) {
|
||||
case eMonstSummon::TYPE: type = STRT_MONST; break;
|
||||
case eMonstSummon::TYPE: type = STRT_MONST; i--; break;
|
||||
case eMonstSummon::LEVEL: type = STRT_SUMMON; break;
|
||||
case eMonstSummon::SPECIES: type = STRT_RACE; break;
|
||||
}
|
||||
i = choose_text(type, i, &me, "Summon what?");
|
||||
if(type == STRT_MONST) i++;
|
||||
abil_params.summon.what = i;
|
||||
fill_monst_abil_detail(me, monst, abil, abil_params);
|
||||
return true;
|
||||
@@ -1312,6 +1332,8 @@ static bool edit_monst_abil_detail(cDialog& me, std::string hit, cMonster& monst
|
||||
if(abil_dlg.accepted())
|
||||
iter->second = abil_params;
|
||||
put_monst_abils_in_dlog(me, monst);
|
||||
size_t iShow = std::distance(monst.abil.begin(), iter);
|
||||
dynamic_cast<cStack&>(me["abils"]).setPage(iShow / 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user