Merge pull request from ennorehling/develop

the latest in function-pointer removal
This commit is contained in:
Enno Rehling 2017-03-04 21:18:13 +01:00 committed by GitHub
commit 21b01aa4c2
106 changed files with 1400 additions and 1510 deletions

2
clibs

@ -1 +1 @@
Subproject commit 27c8b3202b52766465743c3324fc0b52c5ba4b11
Subproject commit b91413316ce13044c555084a9f605983586107b4

View file

@ -5,9 +5,7 @@
<item weight="200" score="200">
<construction skill="mining" minskill="8"/>
</item>
<resourcelimit>
<modifier type="require" building="mine"/>
</resourcelimit>
<modifier type="require" building="mine"/>
</resource>
<resource name="adamantiumaxe">

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="plate">
<item weight="400" score="150">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="armorer" minskill="4">
<requirement type="iron" quantity="5"/>
</construction>

View file

@ -61,16 +61,8 @@
<item weight="0" score="6000"/>
</resource>
<resource name="aoc" appearance="amulet">
<item weight="100">
<function name="use" value="use_birthdayamulet"/>
</item>
</resource>
<resource name="dreameye">
<item weight="100">
<function name="use" value="use_tacticcrystal"/>
</item>
<item weight="100" use="yes" />
</resource>
<resource name="pegasus">
@ -78,9 +70,7 @@
</resource>
<resource name="elvenhorse">
<item weight="5000" notlost="yes" big="yes" score="6000" capacity="7000" animal="yes">
<function name="give" value="givehorses"/>
</item>
<item weight="5000" notlost="yes" big="yes" score="6000" capacity="7000" animal="yes"/>
</resource>
<resource name="dolphin">
@ -100,39 +90,34 @@
</resource>
<!-- XE items -->
<resource name="studypotion" appearance="vial">
<!-- gives user one free learning attempt -->
<item weight="0" use="yes" />
</resource>
<resource name="skillpotion" appearance="vial">
<!-- gives user one free learning attempt -->
<item weight="0">
<function name="use" value="use_skillpotion"/>
</item>
<item weight="0" use="yes" />
</resource>
<resource name="manacrystal" appearance="amulet">
<!-- gives user free aura -->
<item weight="0">
<function name="use" value="use_manacrystal"/>
</item>
<item weight="0" use="yes" />
</resource>
<!-- xmas items -->
<resource name="mistletoe">
<!-- Sets the chance of escape in a fight to 100 percent -->
<item notlost="yes" weight="0">
<function name="use" value="usemistletoe"/>
</item>
<item notlost="yes" weight="0" use="yes" />
</resource>
<resource name="speedsail">
<item weight="0">
<function name="use" value="use_speedsail"/>
</item>
<item weight="0" use="yes" />
</resource>
<!-- items -->
<resource name="antimagic" appearance="amulet">
<item weight="0" score="2000">
<function name="use" value="use_antimagiccrystal"/>
</item>
<item weight="0" score="2000" use="yes" />
</resource>
<resource name="catapultammo">

View file

@ -4,8 +4,7 @@
<!-- potions -->
<resource name="p0" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
<construction skill="alchemy" minskill="2">
<requirement type="h4"/>
@ -15,8 +14,7 @@
</resource>
<resource name="goliathwater" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
<construction skill="alchemy" minskill="2">
<requirement type="h6"/>
@ -26,8 +24,7 @@
</resource>
<resource name="truthpotion" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
<construction skill="alchemy" minskill="2">
<requirement type="h0"/>
@ -37,8 +34,7 @@
</resource>
<resource name="p2" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
<construction skill="alchemy" minskill="2">
<requirement type="h5"/>
@ -48,8 +44,7 @@
</resource>
<resource name="p3" appearance="vial">
<item weight="0" score="60">
<function name="use" value="usepotion"/>
<item weight="0" score="60" use="yes">
<potion level="2"/>
<construction skill="alchemy" minskill="4">
<requirement type="h14"/>
@ -61,8 +56,7 @@
<resource name="ointment" appearance="vial">
<!-- Wundsalbe -->
<item weight="0" score="60">
<function name="use" value="usehealingpotion"/>
<item weight="0" score="60" use="yes">
<potion level="2"/>
<construction skill="alchemy" minskill="4">
<requirement type="h19"/>
@ -74,8 +68,7 @@
<resource name="peasantblood" appearance="vial">
<!-- Bauernblut -->
<item weight="0" score="60">
<function name="use" value="usebloodpotion"/>
<item weight="0" score="60" use="yes">
<potion level="2"/>
<construction skill="alchemy" minskill="4">
<requirement type="h17"/>
@ -87,8 +80,7 @@
</resource>
<resource name="p6" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
<construction skill="alchemy" minskill="6">
<requirement type="h9"/>
@ -100,8 +92,7 @@
</resource>
<resource name="p7" appearance="vial">
<item weight="0" score="90">
<function name="useonother" value="usefoolpotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
<construction skill="alchemy" minskill="6">
<requirement type="h2"/>
@ -113,8 +104,7 @@
</resource>
<resource name="nestwarmth" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usewarmthpotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
<construction skill="alchemy" minskill="6">
<requirement type="h18"/>
@ -126,8 +116,7 @@
</resource>
<resource name="p9" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
<construction skill="alchemy" minskill="6">
<requirement type="h4"/>
@ -139,8 +128,7 @@
</resource>
<resource name="p10" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
<construction skill="alchemy" minskill="6">
<requirement type="h19"/>
@ -152,8 +140,7 @@
</resource>
<resource name="p11" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<item weight="0" score="120" use="yes">
<potion level="4"/>
<construction skill="alchemy" minskill="8">
<requirement type="h14"/>
@ -166,8 +153,7 @@
</resource>
<resource name="p13" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<item weight="0" score="120" use="yes">
<potion level="4"/>
<construction skill="alchemy" minskill="8">
<requirement type="h5"/>
@ -181,8 +167,7 @@
</resource>
<resource name="p14" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<item weight="0" score="120" use="yes">
<potion level="4"/>
<construction skill="alchemy" minskill="8">
<requirement type="h6"/>

View file

@ -1458,12 +1458,6 @@
<string name="aots_p">
<text locale="de">Amulette des wahren Sehens</text>
</string>
<string name="aoc">
<text locale="de">Katzenamulett</text>
</string>
<string name="aoc_p">
<text locale="de">Katzenamulette</text>
</string>
<string name="roi">
<text locale="de">Ring der Unsichtbarkeit</text>
</string>

View file

@ -444,12 +444,6 @@
<string name="ao_chastity_p">
<text locale="en">amulets of chastity</text>
</string>
<string name="aoc">
<text locale="en">amulet of the kitten</text>
</string>
<string name="aoc_p">
<text locale="en">amulets of the kitten</text>
</string>
<string name="aod">
<text locale="en">amulet of darkness</text>
</string>

View file

@ -458,12 +458,6 @@
<string name="ao_chastity_p">
<text locale="fr">amulettes de chasteté</text>
</string>
<string name="aoc">
<text locale="fr">amulette du chaton</text>
</string>
<string name="aoc_p">
<text locale="fr">amulettes du chaton</text>
</string>
<string name="aod">
<text locale="fr">amulette de ténčbres</text>
</string>

View file

@ -1,11 +1,6 @@
<?xml version="1.0"?>
<resource name="horse" limited="yes">
<item big="yes" weight="5000" score="10" capacity="7000" animal="yes">
<construction skill="training" minskill="1"/>
<function name="give" value="givehorses"/>
<construction skill="training" minskill="1" />
</item>
<resourcelimit>
<function name="produce" value="lua_produceresource"/>
<function name="limit" value="lua_limitresource"/>
</resourcelimit>
</resource>

View file

@ -1,5 +1,4 @@
<?xml version="1.0"?>
<resource name="hp" pooled="false">
<function name="change" value="lua_changeresource"/>
<function name="get" value="lua_getresource"/>
</resource>

View file

@ -1,11 +1,9 @@
<?xml version="1.0"?>
<resource name="iron" limited="yes" material="yes">
<item weight="500" score="10">
<construction skill="mining" minskill="1"/>
</item>
<resourcelimit>
<item weight="500" score="10">
<construction skill="mining" minskill="1"/>
</item>
<modifier building="mine" type="skill" value="1"/>
<modifier building="mine" type="material" value="0.5"/>
<modifier race="dwarf" type="material" value="0.60"/>
</resourcelimit>
</resource>

View file

@ -1,9 +1,7 @@
<?xml version="1.0"?>
<resource name="laen" limited="yes" material="yes">
<item weight="200" score="100">
<construction skill="mining" minskill="7"/>
</item>
<resourcelimit>
<item weight="200" score="100">
<construction skill="mining" minskill="7"/>
</item>
<modifier type="require" building="mine"/>
</resourcelimit>
</resource>

View file

@ -1,12 +1,8 @@
<?xml version="1.0"?>
<resource name="log">
<item weight="500" score="10">
<construction skill="forestry" minskill="1"/>
</item>
<resourcelimit>
<resource name="log" limited="yes">
<item weight="500" score="10">
<construction skill="forestry" minskill="1"/>
</item>
<modifier building="sawmill" type="skill" value="1"/>
<modifier building="sawmill" type="material" value="0.5"/>
<function name="produce" value="lua_produceresource"/>
<function name="limit" value="lua_limitresource"/>
</resourcelimit>
</resource>

View file

@ -1,12 +1,8 @@
<?xml version="1.0"?>
<resource name="mallorn">
<item weight="500" score="30">
<construction skill="forestry" minskill="2"/>
</item>
<resourcelimit>
<resource name="mallorn" limited="yes">
<item weight="500" score="30">
<construction skill="forestry" minskill="2"/>
</item>
<modifier building="sawmill" type="skill" value="1"/>
<modifier building="sawmill" type="material" value="0.5"/>
<function name="produce" value="lua_produceresource"/>
<function name="limit" value="lua_limitresource"/>
</resourcelimit>
</resource>

View file

@ -3,8 +3,4 @@
<item weight="10" score="100">
<construction skill="herbalism" minskill="4"/>
</item>
<resourcelimit>
<function name="produce" value="lua_produceresource"/>
<function name="limit" value="lua_limitresource"/>
</resourcelimit>
</resource>

View file

@ -1,5 +1,4 @@
<?xml version="1.0"?>
<resource name="peasant" pooled="false">
<function name="change" value="lua_changeresource"/>
<function name="get" value="lua_getresource"/>
</resource>

View file

@ -3,8 +3,4 @@
<item weight="10" score="50">
<construction skill="herbalism" minskill="3"/>
</item>
<resourcelimit>
<function name="produce" value="lua_produceresource"/>
<function name="limit" value="lua_limitresource"/>
</resourcelimit>
</resource>

View file

@ -1,11 +1,9 @@
<?xml version="1.0"?>
<resource name="stone" limited="yes" material="yes">
<item weight="6000" score="10" big="yes">
<construction skill="quarrying" minskill="1"/>
</item>
<resourcelimit>
<item weight="6000" score="10" big="yes">
<construction skill="quarrying" minskill="1"/>
</item>
<modifier building="quarry" type="skill" value="1"/>
<modifier building="quarry" type="material" value="0.5"/>
<modifier race="troll" type="material" value="0.75"/>
</resourcelimit>
</resource>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="axe">
<item weight="200">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="3">
<requirement type="log" quantity="1"/>
<requirement type="iron" quantity="1"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="greatbow">
<item weight="100">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="5">
<modifier function="mod_elves_only"/>
<requirement type="mallorn" quantity="2"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="greatsword">
<item weight="200" score="30">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="4">
<requirement type="iron" quantity="2"/>
</construction>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="halberd">
<item weight="200">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="3">
<requirement type="log" quantity="2"/>
<requirement type="iron" quantity="1"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="lance">
<item weight="200">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="2">
<requirement type="log" quantity="2"/>
</construction>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="mallornlance">
<item weight="100">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="5">
<requirement type="mallorn" quantity="2"/>
</construction>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="rustyaxe">
<item weight="200">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="3">
<requirement type="log" quantity="1"/>
<requirement type="iron" quantity="1"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="rustyhalberd">
<item weight="200" score="20">
<function name="canuse" value="lua_canuse_item"/>
<construction skill="weaponsmithing" minskill="3">
<requirement type="iron" quantity="1"/>
<requirement type="log" quantity="1"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="plate">
<item weight="400" score="150">
<function name="canuse" value="lua_canuse_item"/>
<item weight="400" score="150" deny="goblin">
<construction skill="armorer" minskill="4">
<requirement type="iron" quantity="4"/>
</construction>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="scale">
<item weight="300" score="150">
<function name="canuse" value="lua_canuse_item"/>
<item weight="300" score="150" allow="dwarf halfling">
<construction skill="armorer" minskill="5">
<modifier function="mod_dwarves_only"/>
<requirement type="iron" quantity="2"/>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="towershield">
<item weight="200" score="60">
<function name="canuse" value="lua_canuse_item"/>
<item weight="200" score="60" allow="dwarf">
<construction skill="armorer" minskill="4">
<modifier function="mod_dwarves_only"/>
<requirement type="iron" quantity="1"/>

View file

@ -7,83 +7,72 @@
<resource name="ointment" appearance="vial">
<!-- Wundsalbe -->
<item weight="0" score="60">
<function name="use" value="usehealingpotion"/>
<item weight="0" score="60" use="yes">
<potion level="2"/>
</item>
</resource>
<resource name="p13" appearance="vial">
<!-- Elixier der Macht -->
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<item weight="0" score="120" use="yes">
<potion level="4"/>
</item>
</resource>
<resource name="p3" appearance="vial">
<!-- Schaffenstrunk -->
<item weight="0" score="60">
<function name="use" value="usepotion"/>
<item weight="0" score="60" use ="yes">
<potion level="2"/>
</item>
</resource>
<resource name="p14" appearance="vial">
<!-- Heiltrank -->
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<item weight="0" score="120" use="yes">
<potion level="4"/>
</item>
</resource>
<resource name="p0" appearance="vial">
<!-- Siebenmeilentee -->
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
</item>
</resource>
<resource name="p2" appearance="vial">
<!-- Wasser des Lebens -->
<item weight="0" score="30">
<function name="use" value="usepotion_delayed"/>
<item weight="0" score="30" use="yes">
<potion level="1"/>
</item>
</resource>
<resource name="peasantblood" appearance="vial">
<!-- Bauernblut -->
<item weight="0" score="60">
<function name="use" value="usebloodpotion"/>
<item weight="0" score="60" use="yes">
<potion level="2"/>
</item>
</resource>
<resource name="p9" appearance="vial">
<!-- Pferdeglück -->
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<item weight="0" score="90" use="yes">
<potion level="3"/>
</item>
</resource>
<resource name="charger">
<item big="yes" weight="5000" score="10" capacity="7000" animal="yes">
<item big="yes" weight="5000" score="20" capacity="7000" animal="yes">
<construction skill="training" minskill="4">
<requirement type="money" quantity="200"/>
<requirement type="iron" quantity="1"/>
<requirement type="horse" quantity="1"/>
</construction>
<function name="give" value="givehorses"/>
</item>
</resource>
<resource name="xmastree">
<item weight="0">
<function name="use" value="lua_useitem"/>
</item>
<item weight="0" use="yes" />
</resource>
</resources>

View file

@ -71,7 +71,11 @@
<familiar race="ghost"/>
</race>
<race name="halfling" defensemodifier="1" magres="5" maxaura="1.0" regaura="1.0" recruitcost="100" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
<race name="halfling" defensemodifier="1" magres="5" maxaura="1.0"
regaura="1.0" recruitcost="100" maintenance="10" weight="1000"
capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
giveunit="yes" getitem="yes" equipment="yes">
<ai splitsize="10000" moverandom="yes" learn="yes"/>
<param name="other_race" value="dwarf"/>
<param name="luxury_trade" value="600"/>
@ -116,7 +120,11 @@
<familiar race="ghost"/>
</race>
<race name="elf" magres="10" maxaura="1.0" regaura="1.1" recruitcost="200" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
<race name="elf" magres="10" maxaura="1.0" regaura="1.1"
recruitcost="200" maintenance="10" weight="1000" capacity="540"
speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
giveunit="yes" getitem="yes" equipment="yes" >
<ai splitsize="10000" moverandom="yes" learn="yes"/>
<skill name="armorer" modifier="-1"/>
<skill name="bow" modifier="2"/>
@ -156,7 +164,11 @@
<familiar race="rat"/>
</race>
<race name="dwarf" magres="5" maxaura="1.0" regaura="0.9" recruitcost="240" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
<race name="dwarf" magres="5" maxaura="1.0" regaura="0.9"
recruitcost="240" maintenance="10" weight="1000" capacity="540"
speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
giveunit="yes" getitem="yes" equipment="yes">
<ai splitsize="10000" moverandom="yes" learn="yes"/>
<skill name="armorer" modifier="2"/>
<skill name="bow" modifier="-1"/>

View file

@ -1,10 +1,8 @@
<?xml version="1.0"?>
<resource name="iron" limited="yes" material="yes">
<item weight="500" score="10">
<construction skill="mining" minskill="1"/>
</item>
<resourcelimit>
<item weight="500" score="10">
<construction skill="mining" minskill="1"/>
</item>
<modifier building="mine" type="skill" value="1"/>
<modifier building="mine" type="material" value="0.5"/>
</resourcelimit>
</resource>

View file

@ -1,10 +1,8 @@
<?xml version="1.0"?>
<resource name="stone" limited="yes" material="yes">
<item weight="6000" score="10" big="yes">
<construction skill="quarrying" minskill="1"/>
</item>
<resourcelimit>
<item weight="6000" score="10" big="yes">
<construction skill="quarrying" minskill="1"/>
</item>
<modifier building="quarry" type="skill" value="1"/>
<modifier building="quarry" type="material" value="0.5"/>
</resourcelimit>
</resource>

View file

@ -1,18 +1,18 @@
<?xml version="1.0"?>
<resources xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="config://core/weapons/axe.xml"/>
<xi:include href="config://core/weapons/bow.xml"/>
<xi:include href="config://core/weapons/catapult.xml"/>
<xi:include href="config://core/weapons/lance.xml"/>
<xi:include href="config://core/weapons/mallornbow.xml"/>
<xi:include href="config://core/weapons/mallornspear.xml"/>
<xi:include href="config://core/weapons/rep_crossbow.xml"/>
<xi:include href="config://core/weapons/runesword.xml"/>
<xi:include href="config://core/weapons/rustyaxe.xml"/>
<xi:include href="config://core/weapons/rustysword.xml"/>
<xi:include href="config://core/weapons/spear.xml"/>
<xi:include href="config://core/weapons/sword.xml"/>
<xi:include href="config://core/weapons/firesword.xml"/>
<xi:include href="config://game/weapons/rep_crossbow.xml"/>
<xi:include href="config://game/weapons/lance.xml"/>
<xi:include href="config://game/weapons/axe.xml"/>
<xi:include href="config://game/weapons/crossbow.xml"/>
<xi:include href="config://game/weapons/greatbow.xml"/>
<xi:include href="config://game/weapons/greatsword.xml"/>

13
res/e3a/weapons/axe.xml Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<resource name="axe">
<item weight="200" deny="goblin">
<construction skill="weaponsmithing" minskill="3">
<requirement type="log" quantity="1"/>
<requirement type="iron" quantity="1"/>
</construction>
<weapon cut="true" skill="melee" offmod="1" defmod="-2">
<damage type="rider" value="2d6+4"/>
<damage type="footman" value="2d6+4"/>
</weapon>
</item>
</resource>

View file

@ -4,8 +4,7 @@
* has lower damage
-->
<resource name="greatbow">
<item weight="100">
<function name="canuse" value="lua_canuse_item"/>
<item weight="100" allow="elf">
<construction skill="weaponsmithing" minskill="5">
<modifier function="mod_elves_only"/>
<requirement type="mallorn" quantity="2"/>

View file

@ -3,8 +3,7 @@
1. you cannt use this with cavalry
-->
<resource name="halberd">
<item weight="200">
<function name="canuse" value="lua_canuse_item"/>
<item weight="200" deny="goblin">
<construction skill="weaponsmithing" minskill="3">
<requirement type="log" quantity="2"/>
<requirement type="iron" quantity="1"/>

12
res/e3a/weapons/lance.xml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<resource name="lance">
<item weight="200" deny="goblin">
<construction skill="weaponsmithing" minskill="2">
<requirement type="log" quantity="2"/>
</construction>
<weapon pierce="true" skill="polearm" offmod="0" defmod="-2">
<damage type="footman" value="1d5"/>
<damage type="rider" value="2d6+5"/>
</weapon>
</item>
</resource>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="mallornlance">
<item weight="100">
<function name="canuse" value="lua_canuse_item"/>
<item weight="100" deny="goblin">
<construction skill="weaponsmithing" minskill="5">
<requirement type="mallorn" quantity="2"/>
</construction>

View file

@ -1,7 +1,6 @@
<?xml version="1.0"?>
<resource name="rep_crossbow">
<item weight="100">
<function name="canuse" value="lua_canuse_item"/>
<item weight="100" allow="dwarf halfling">
<construction skill="weaponsmithing" minskill="5">
<modifier function="mod_dwarves_only"/>
<requirement type="log" quantity="1"/>

View file

@ -3,8 +3,7 @@
1. you cannot use this with cavalry
-->
<resource name="rustyhalberd">
<item weight="200" score="20">
<function name="canuse" value="lua_canuse_item"/>
<item weight="200" score="20" deny="goblin">
<construction skill="weaponsmithing" minskill="3">
<requirement type="iron" quantity="1"/>
<requirement type="log" quantity="1"/>

View file

@ -3,16 +3,12 @@
<resource name="aurapotion50">
<function name="change" value="changeitem"/>
<item weight="0">
<function name="use" value="use_aurapotion50"/>
</item>
<item weight="0" use="yes" />
</resource>
<resource name="bagpipeoffear">
<function name="change" value="changeitem"/>
<item weight="0">
<function name="use" value="use_bagpipeoffear"/>
</item>
<item weight="0" use="yes"/>
</resource>
</resources>

View file

@ -17,21 +17,15 @@
</resource>
<resource name="snowman">
<item notlost="yes" weight="1">
<function name="use" value="lua_useitem"/>
</item>
<item notlost="yes" weight="1" use="yes" />
</resource>
<resource name="snowglobe">
<item notlost="yes" weight="1">
<function name="use" value="lua_useitem"/>
</item>
<item notlost="yes" weight="1" use="yes" />
</resource>
<resource name="ring_of_levitation" appearance="ring">
<item notlost="yes" weight="0" cursed="true">
<function name="use" value="lua_useitem"/>
</item>
<item notlost="yes" weight="0" cursed="true" use="yes" />
</resource>
<resource name="birthdaycake">
@ -44,52 +38,38 @@
<!-- ambassador rewards -->
<resource name="seashell">
<item cursed="true" weight="0">
<function name="use" value="lua_useitem"/>
</item>
<item cursed="true" weight="0" use="yes" />
</resource>
<!-- xmas 2005 -->
<resource name="stardust" appearance="vial">
<item weight="0">
<function name="use" value="lua_useitem"/>
</item>
<item weight="0" use="yes" />
</resource>
<!-- xmas 2006 -->
<resource name="xmastree">
<item weight="0">
<function name="use" value="lua_useitem"/>
</item>
<item weight="0" use="yes" />
</resource>
<!-- museum items -->
<resource name="questkey1" appearance="key">
<!-- Key for an old quest. placeholder item -->
<item notlost="yes" weight="0" >
<function name="use" value="use_museumkey"/>
</item>
<item notlost="yes" weight="0" use="yes" />
</resource>
<resource name="questkey2" appearance="key">
<!-- Key for an old quest. placeholder item -->
<item notlost="yes" weight="0" >
<function name="use" value="use_museumkey"/>
</item>
<item notlost="yes" weight="0" use="yes" />
</resource>
<resource name="museumexitticket">
<!-- you get your stuff back when leaving the museum -->
<item notlost="yes" weight="0">
<function name="use" value="use_museumexitticket"/>
</item>
<item notlost="yes" weight="0" use="yes" />
</resource>
<resource name="museumticket">
<!-- you get your stuff back when leaving the museum -->
<item weight="0">
<function name="use" value="use_museumticket"/>
</item>
<item weight="0" use="yes" />
</resource>
<!-- gimmicks, etc. -->
@ -98,27 +78,13 @@
<item notlost="yes" cursed="true" weight="0"/>
</resource>
<resource name="ao_daemon">
<!-- summons igjarjuk -->
<item weight="0" score="6000" notlost="true" cursed="true">
<function name="use" value="useigjarjuk"/>
<function name="give" value="giveigjarjuk"/>
</item>
</resource>
<resource name="griphonwing">
<!-- this lets you leave the arena -->
<item weight="0" score="6000" notlost="true" cursed="true">
<function name="use" value="leave_arena"/>
<function name="give" value="giveigjarjuk"/>
</item>
<resource name="aoc" appearance="amulet">
<item weight="100" use="yes" />
</resource>
<resource name="eyeofdragon">
<!-- the arena gate, for one-time entry -->
<item weight="0" score="0">
<function name="use" value="enter_arena"/>
</item>
<item weight="0" score="0"/>
</resource>
<resource name="jadee_ring" appearance="ring">

View file

@ -116,18 +116,6 @@
<text locale="de">Eine Geburtstagstorte mit 10 Kerzen. Herzlichen Glückwunsch, Eressea!</text>
<text locale="en">A birthday cake with 10 candles. Happy Birthday, Eressea!</text>
</string>
<string name="griphonwing">
<text locale="de">Dieses Fluggerät aus der Schmiede der Zwerge von Celeband galt wie die
'Ebene der Herausforderung' seit Urzeiten als verschollen, ja man
zweifelte seine Existenz an. Die Sage überliefert, das derjenige, der
sie auf der Spitze des Turmes seiner Gesinnung benutzt, als einziger
die 'Ebene der Herausforderungen' verlassen kann.</text>
</string>
<string name="ao_daemon">
<text locale="de">Glückwunsch, mein Kind. Du bist im Besitz des mächtigsten
Artefaktes Eresseas. Ein Fluch, sagt man, liege auf ihm, denn
niemand hat es bisher lange sein Eigen genannt...</text>
</string>
<string name="cookie">
<text locale="de">Kleines trockenes Dauergebäck, m od. s; - u. -es, - u. -e</text>
</string>
@ -374,29 +362,6 @@
</string>
<!-- art rewards end -->
<!-- igjarjuk queste begin -->
<string name="ao_daemon">
<text locale="de">Auge des Dämon</text>
<text locale="en">eye of the demon</text>
<text locale="fr">oeil du démon</text>
</string>
<string name="ao_daemon_p">
<text locale="de">Augen des Dämon</text>
<text locale="en">eyes of the demon</text>
<text locale="fr">oeil du démon</text>
</string>
<string name="griphonwing">
<text locale="de">Schwinge des Greifen</text>
<text locale="en">wing of the gryphon</text>
<text locale="fr">aile du griffon</text>
</string>
<string name="griphonwing_p">
<text locale="de">Schwingen des Greifen</text>
<text locale="en">wings of the gryphon</text>
<text locale="fr">ailes du griffon</text>
</string>
<!-- igjarjuk queste end -->
<string name="rm_adamantium">
<text locale="de">Adamantium</text>
<text locale="en">adamantium</text>
@ -427,5 +392,14 @@
<text locale="de">Adamantiumrüstungen</text>
<text locale="en">adamantium plates</text>
</string>
<string name="aoc">
<text locale="de">Katzenamulett</text>
<text locale="en">amulet of the kitten</text>
<text locale="fr">amulette du chaton</text>
</string>
<string name="aoc_p">
<text locale="en">amulets of the kitten</text>
<text locale="de">Katzenamulette</text>
<text locale="fr">amulettes du chaton</text>
</string>
</strings>

View file

@ -1,14 +0,0 @@
<?xml version="1.0" ?>
<races xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="races/aquarian.xml"/>
<xi:include href="races/cat.xml"/>
<xi:include href="races/demon.xml"/>
<xi:include href="races/dwarf.xml"/>
<xi:include href="races/elf.xml"/>
<xi:include href="races/goblin.xml"/>
<xi:include href="races/halfling.xml"/>
<xi:include href="races/human.xml"/>
<xi:include href="races/insect.xml"/>
<xi:include href="races/orc.xml"/>
<xi:include href="races/troll.xml"/>
</races>

View file

@ -1,24 +0,0 @@
<?xml version="1.0" ?>
<race name="goblin" magres="-5" maxaura="1.0" regaura="1.0"
recruitcost="60" maintenance="6" weight="600" capacity="440"
speed="1.0" hp="16" damage="1d5" unarmedattack="-2" unarmeddefense="0"
playerrace="yes" walk="yes" giveperson="yes" giveunit="yes"
getitem="yes" equipment="yes" healing="2.0">
<ai splitsize="10000" moverandom="yes" learn="yes"/>
<param name="hunger.damage" value="1d8+7"/>
<param name="other_race" value="demon"/>
<param name="recruit_multi" value="0.5"/>
<skill name="building" modifier="1"/>
<skill name="cartmaking" modifier="-1"/>
<skill name="catapult" modifier="1"/>
<skill name="magic" modifier="-99"/>
<skill name="mining" modifier="1"/>
<skill name="roadwork" modifier="-2"/>
<skill name="sailing" modifier="-2"/>
<skill name="shipcraft" modifier="-2"/>
<skill name="tactics" modifier="-2"/>
<skill name="unarmed" modifier="-99"/>
<attack type="1" damage="1d5"/>
<familiar race="rat" default="yes"/>
<familiar race="imp"/>
</race>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" ?>
<race name="goblin" magres="-5" maxaura="1.0" regaura="1.0"
<race name="goblin" magres="-5" maxaura="1.0"
recruitcost="60" maintenance="6" weight="600" capacity="440"
speed="1.0" hp="16" damage="1d5" unarmedattack="-2" unarmeddefense="0"
playerrace="yes" walk="yes" giveperson="yes" giveunit="yes"

View file

@ -1,6 +1,6 @@
<?xml version="1.0" ?>
<race name="goblin" magres="-5" maxaura="1.000000"
regaura="1.000000" recruitcost="40" maintenance="10" weight="600"
recruitcost="40" maintenance="10" weight="600"
capacity="440" speed="1.000000" hp="16" damage="1d5"
unarmedattack="-2" unarmeddefense="0" playerrace="yes" walk="yes"
giveperson="yes" giveunit="yes" getitem="yes" equipment="yes"

View file

@ -1,31 +1,3 @@
-- when appending to this, make sure the item has a canuse-function!
local goblin_denied = " plate lance mallornlance greatbow axe greatsword halberd rustyaxe rustyhalberd towershield scale "
function item_canuse(u, iname)
local race = u.race
if race=="goblin" then
if string.find(goblin_denied, " " .. iname .. " ") then
return false
end
end
if iname=="rep_crossbow" then
-- only dwarves and halflings allowed to use repeating crossbow
return race=="dwarf" or race=="halfling"
end
if iname=="scale" then
-- only dwarves and halflings can use scale
return race=="dwarf" or race=="halfling"
end
if iname=="towershield" then
-- only dwarves allowed to use towershield
return race=="dwarf"
end
if iname=="greatbow" then
-- only elves use greatbow
return race=="elf"
end
return true
end
function building_taxes(b, blevel)
btype = b.type
if btype=="castle" then

View file

@ -1,16 +1,5 @@
-- global functions used in items.xml
if not item_canuse then
-- define a default, everyone can use everything
function item_canuse(u, iname)
return true
end
end
function peasant_getresource(u)
return u.region:get_resource("peasant")
end
function peasant_changeresource(u, delta)
local p = u.region:get_resource("peasant")
p = p + delta
@ -21,10 +10,6 @@ function peasant_changeresource(u, delta)
return p
end
function hp_getresource(u)
return u.hp
end
function hp_changeresource(u, delta)
local hp = u.hp + delta

View file

@ -25,6 +25,7 @@ end
function use_stardust(u, amount)
local p = u.region:get_resource("peasant")
assert(p>0)
p = math.ceil(1.5 * p)
u.region:set_resource("peasant", p)
local msg = usepotion_message(u, "stardust")

View file

@ -1028,3 +1028,34 @@ function test_recruit()
assert_equal(6, u.number)
end
end
function test_give_horses()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
r:set_resource("horse", 0)
u:add_item("horse", 21)
u:add_item("dolphin", 10)
u:add_order("GIB 0 7 PFERD")
u:add_order("GIB 0 5 DELPHIN")
process_orders()
assert_equal(7, r:get_resource("horse"))
assert_equal(5, u:get_item("dolphin"))
assert_equal(14, u:get_item("horse"))
end
function test_give_silver()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
r:set_resource("peasant", 0)
r:set_resource("money", 11)
u:clear_orders()
u:add_item("money", 20)
u:add_order("GIB 0 10 SILBER")
process_orders()
assert_equal(21, r:get_resource("money"))
assert_equal(10, u:get_item("money"))
end

View file

@ -230,25 +230,6 @@ function test_no_uruk()
assert_equal(f1.race, "orc")
end
function test_snowman()
local r = region.create(0, 0, "glacier")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("snowman", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Schneemann")
process_orders()
for u2 in r.units do
if u2.id~=u.id then
assert_equal("snowman", u2.race)
assert_equal(1000, u2.hp)
u = nil
break
end
end
assert_equal(nil, u)
end
function test_block_movement()
eressea.settings.set("rules.guard.base_stop_prob", "0.3")
eressea.settings.set("rules.guard.amulet_stop_prob", "0.0")

View file

@ -8,6 +8,8 @@ require 'tests.e2.destroy'
require 'tests.e2.guard'
require 'tests.e2.spells'
require 'tests.e2.stealth'
require 'tests.e2.items'
require 'tests.items'
require 'tests.orders'
require 'tests.common'
require 'tests.report'

159
scripts/tests/e2/items.lua Normal file
View file

@ -0,0 +1,159 @@
require "lunit"
module("tests.e2.items", package.seeall, lunit.testcase )
function setup()
eressea.free_game()
eressea.settings.set("nmr.timeout", "0")
eressea.settings.set("rules.food.flags", "4")
eressea.settings.set("rules.ship.storms", "0")
eressea.settings.set("rules.encounters", "0")
eressea.settings.set("magic.regeneration.enable", "0")
end
function test_nestwarmth_insect()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "insect", "de")
local u = unit.create(f, r, 1)
local flags = u.flags
u:add_item("nestwarmth", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Nestwaerme")
turn_begin()
turn_process()
assert_equal(flags+64, u.flags) -- UFL_WARMTH
assert_equal(1, u:get_item("nestwarmth"))
assert_equal(1, f:count_msg_type('usepotion'))
turn_end()
end
function test_nestwarmth_other()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
local flags = u.flags
u:add_item("nestwarmth", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Nestwaerme")
turn_begin()
turn_process()
assert_equal(flags, u.flags) -- nothing happens
assert_equal(2, u:get_item("nestwarmth"))
assert_equal(1, f:count_msg_type('error163'))
turn_end()
end
function test_meow()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("aoc", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Katzenamulett")
turn_begin()
turn_process()
assert_equal(1, u:get_item("aoc"))
assert_equal(1, r:count_msg_type('meow'))
turn_end()
end
function test_aurapotion50()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("aurapotion50", 1)
u:set_skill('magic', 10);
u.magic = 'gwyrrd'
u.aura = 0
u:clear_orders()
u:add_order("BENUTZEN 1 Auratrank")
turn_begin()
turn_process()
assert_equal(0, u:get_item("aurapotion50"))
assert_equal(1, f:count_msg_type('aurapotion50'))
assert_equal(50, u.aura)
turn_end()
end
function test_bagpipe()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item("bagpipeoffear", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Dudelsack")
assert_equal(nil, r:get_curse('depression'))
turn_process()
assert_equal(0, r:get_curse('depression'))
assert_equal(1, u:get_item("bagpipeoffear"))
assert_equal(1, f:count_msg_type('bagpipeoffear_faction'))
assert_equal(1, r:count_msg_type('bagpipeoffear_region'))
turn_end()
-- duration is variable, but at least 4
assert_equal(0, r:get_curse('depression'))
end
function test_speedsail()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u.ship = ship.create(r, "boat")
u:add_item("speedsail", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Sonnensegel")
assert_equal(nil, u.ship:get_curse('shipspeed'))
turn_process()
assert_equal(1, u.ship:get_curse('shipspeed'))
assert_equal(1, u:get_item("speedsail"))
assert_equal(1, f:count_msg_type('use_speedsail'))
turn_end()
assert_equal(1, u.ship:get_curse('shipspeed')) -- effect stays forever
end
function test_foolpotion()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item("p7", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Dumpfbackenbrot 4242")
turn_process()
assert_equal(1, u:get_item("p7"))
assert_equal(1, f:count_msg_type('feedback_unit_not_found'))
local u2 = unit.create(f, r, 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Dumpfbackenbrot " .. itoa36(u2.id))
turn_process()
assert_equal(1, u:get_item("p7"))
assert_equal(1, f:count_msg_type('error64'))
u:set_skill("stealth", 1);
turn_process()
assert_equal(0, u:get_item("p7"))
assert_equal(1, f:count_msg_type('givedumb'))
turn_end()
end
function test_snowman()
local r = region.create(0, 0, "glacier")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("snowman", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Schneemann")
process_orders()
for u2 in r.units do
if u2.id~=u.id then
assert_equal("snowman", u2.race)
assert_equal(1000, u2.hp)
u = nil
break
end
end
assert_equal(nil, u)
end

View file

@ -4,8 +4,10 @@ require 'tests.e3.spells'
require 'tests.e3.rules'
require 'tests.e3.parser'
require 'tests.e3.morale'
require 'tests.e3.items'
require 'tests.orders'
require 'tests.common'
require 'tests.items'
-- require 'tests.report'
require 'tests.magicbag'
require 'tests.process'

View file

@ -0,0 +1,76 @@
require "lunit"
module("tests.e3.items", package.seeall, lunit.testcase )
function setup()
eressea.game.reset()
eressea.settings.set("rules.food.flags", "4") -- food is free
eressea.settings.set("NewbieImmunity", "0")
end
function test_give_horses()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
r:set_resource("horse", 0)
u:add_item("charger", 20)
u:add_order("GIB 0 10 Streitross")
process_orders()
assert_equal(10, r:get_resource("horse"))
assert_equal(10, u:get_item("charger"))
end
function test_goblins()
local r = region.create(0, 0, "plain")
local f1 = faction.create("goblin@eressea.de", "goblin", "de")
local f2 = faction.create("dwarf@eressea.de", "dwarf", "de")
local f3 = faction.create("elf@eressea.de", "elf", "de")
local ud = unit.create(f1, r, 1)
local uh = unit.create(f1, r, 1)
uh.race = "halfling"
local u2 = unit.create(f2, r, 1)
local u3 = unit.create(f3, r, 1)
local restricted = {
"towershield", "rep_crossbow", "plate", "lance",
"mallornlance", "greatbow", "greataxe", "axe", "scale",
"plate", "halberd", "greatsword", "rustyhalberd"
}
for k, v in ipairs(restricted) do
ud:add_item(v, 1)
uh:add_item(v, 1)
u2:add_item(v, 1)
u3:add_item(v, 1)
end
uh:add_order("ATTACKIERE " .. itoa36(u2.id))
uh:add_order("ATTACKIERE " .. itoa36(u3.id))
ud:add_order("ATTACKIERE " .. itoa36(u2.id))
ud:add_order("ATTACKIERE " .. itoa36(u3.id))
process_orders()
end
function test_make_horse()
eressea.settings.set("rules.horses.growth", "0")
local r = region.create(0, 0, "plain")
local f = faction.create("horses@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:set_skill("training", 4)
r:set_resource("horse", 100)
u:add_order("MACHE 1 PFERD")
process_orders()
assert_equal(1, u:get_item("horse"))
assert_equal(99, r:get_resource("horse"))
u:clear_orders()
u:add_order("MACHE 1 STREITROSS")
u:add_item("money", 200)
u:add_item("iron", 1)
process_orders()
assert_equal(1, u:get_item("charger"))
assert_equal(0, u:get_item("horse"))
assert_equal(0, u:get_item("iron"))
assert_equal(0, u:get_item("money"))
assert_equal(99, r:get_resource("horse"))
end

View file

@ -626,11 +626,7 @@ function test_give_50_percent_of_money()
u1:add_order("GIB " .. itoa36(u2.id) .. " 221 Silber")
u2:clear_orders()
u2:add_order("HELFEN " .. itoa36(u1.faction.id) .. " GIB")
u2:add_item("horse", 100)
u2:add_order("GIB 0 ALLES PFERD")
local h = r:get_resource("horse")
process_orders()
assert_true(r:get_resource("horse")>=h+100)
assert_equal(m1-221, u1:get_item("money"))
assert_equal(m2+110, u2:get_item("money"))
end
@ -990,4 +986,4 @@ function test_bug2187()
-- write_report(f)
set_rule("rules.food.flags", "4")
end
end

169
scripts/tests/items.lua Normal file
View file

@ -0,0 +1,169 @@
require "lunit"
module("tests.items", package.seeall, lunit.testcase )
function setup()
eressea.free_game()
eressea.settings.set("nmr.timeout", "0")
eressea.settings.set("rules.food.flags", "4")
eressea.settings.set("rules.ship.storms", "0")
eressea.settings.set("rules.encounters", "0")
eressea.settings.set("magic.regeneration.enable", "0")
end
function test_mistletoe_okay()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item('mistletoe', 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Mistelzweig")
assert_false(u:has_attrib('fleechance'))
turn_process()
assert_true(u:has_attrib('fleechance'))
assert_equal(1, u:get_item('mistletoe'))
assert_equal(1, f:count_msg_type('use_item'))
turn_end()
end
function test_mistletoe_fail()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item('mistletoe', 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Mistelzweig")
assert_false(u:has_attrib('fleechance'))
u.number = 2
turn_process()
assert_false(u:has_attrib('fleechance'))
assert_equal(1, u:get_item('mistletoe'))
assert_equal(1, f:count_msg_type('use_singleperson'))
turn_end()
end
function test_dreameye()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("dreameye", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Traumauge")
assert_nil(u:get_curse('skillmod'))
turn_begin()
turn_process()
assert_not_nil(u:get_curse('skillmod'))
assert_equal(1, u:get_item("dreameye"))
assert_equal(1, f:count_msg_type('use_tacticcrystal'))
turn_end()
assert_nil(u:get_curse('skillmod'))
end
function test_manacrystal()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("manacrystal", 2)
u:clear_orders()
u.magic = "gwyrrd"
u:set_skill('magic', 1)
u.aura = 0
u:add_order("BENUTZEN 1 Astralkristall")
turn_begin()
turn_process()
assert_equal(1, u:get_item("manacrystal"))
assert_equal(25, u.aura)
assert_equal(1, f:count_msg_type('manacrystal_use'))
turn_end()
end
function test_skillpotion()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("skillpotion", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Talenttrunk")
process_orders()
assert_equal(1, u:get_item("skillpotion"))
assert_equal(1, f:count_msg_type('skillpotion_use'))
end
function test_studypotion()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item("studypotion", 2)
u:clear_orders()
u:add_order("LERNE Unterhaltung")
u:add_order("BENUTZEN 1 Lerntrank")
turn_process()
-- cannot sense the "learning" attribute, because study_cmd
-- removes it during processing :(
assert_equal(1, u:get_item("studypotion"))
turn_end()
end
function test_antimagic()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
turn_begin()
u:add_item("antimagic", 2)
u:clear_orders()
u:add_order("BENUTZEN 1 Antimagiekristall")
assert_equal(nil, r:get_curse('antimagiczone'))
turn_process()
assert_equal(5, r:get_curse('antimagiczone'))
assert_equal(1, r:count_msg_type('use_antimagiccrystal'))
assert_equal(1, u:get_item("antimagic"))
turn_end()
assert_equal(5, r:get_curse('antimagiczone')) -- haelt zwei wochen
turn_end() -- hack: age the curse again
assert_equal(nil, r:get_curse('antimagiczone'))
end
function test_ointment()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
local hp = u.hp
u.hp = 1
u:add_item("ointment", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Wundsalbe")
process_orders()
assert_equal(0, u:get_item("ointment"))
assert_equal(1, f:count_msg_type('usepotion'))
assert_equal(hp, u.hp)
end
function test_bloodpotion_demon()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "demon", "de")
local u = unit.create(f, r, 1)
u:add_item("peasantblood", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Bauernblut")
process_orders()
assert_equal(0, u:get_item("peasantblood"))
assert_equal(1, f:count_msg_type('usepotion'))
assert_equal("demon", u.race)
end
function test_bloodpotion_other()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u = unit.create(f, r, 1)
u:add_item("peasantblood", 1)
u:clear_orders()
u:add_order("BENUTZEN 1 Bauernblut")
process_orders()
assert_equal(0, u:get_item("peasantblood"))
assert_equal(1, f:count_msg_type('usepotion'))
assert_equal("smurf", u.race)
end

View file

@ -187,6 +187,15 @@ target_link_libraries(eressea
${INIPARSER_LIBRARIES}
)
add_executable(convert convert.c)
target_link_libraries(convert
game
${LUA_MATH_LIBRARY}
${STORAGE_LIBRARIES}
${CLIBS_LIBRARIES}
${INIPARSER_LIBRARIES}
)
set(TESTS_SRC
monsters.test.c
names.test.c
@ -268,6 +277,7 @@ endif(CURSES_FOUND)
if (LIBXML2_FOUND)
include_directories (${LIBXML2_INCLUDE_DIR})
target_link_libraries(eressea ${LIBXML2_LIBRARIES})
target_link_libraries(convert ${LIBXML2_LIBRARIES})
target_link_libraries(test_eressea ${LIBXML2_LIBRARIES})
add_definitions(-DUSE_LIBXML2)
endif (LIBXML2_FOUND)

View file

@ -25,6 +25,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* attributes includes */
#include "follow.h"
#include "fleechance.h"
#include "hate.h"
#include "iceberg.h"
#include "key.h"
@ -58,6 +59,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <storage.h>
attrib_type at_unitdissolve = {
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
};
@ -92,6 +94,7 @@ void register_attributes(void)
at_register(&at_woodcount);
/* neue UNIT-Attribute */
at_register(&at_fleechance);
at_register(&at_siege);
at_register(&at_effect);
at_register(&at_private);
@ -112,6 +115,7 @@ void register_attributes(void)
at_register(&at_germs);
at_deprecate("hurting", a_readint); /* an old arena attribute */
at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */
at_deprecate("orcification", a_readint); /* required for old datafiles */
at_deprecate("lua", read_ext); /* required for old datafiles */

View file

@ -38,8 +38,3 @@ attrib *make_fleechance(float fleechance)
a->data.flt = fleechance;
return a;
}
void init_fleechance(void)
{
at_register(&at_fleechance);
}

View file

@ -25,7 +25,6 @@ extern "C" {
extern struct attrib_type at_fleechance;
struct attrib *make_fleechance(float fleechance);
void init_fleechance(void);
#ifdef __cplusplus
}

View file

@ -576,10 +576,7 @@ static weapon *select_weapon(const troop t, bool attacking,
static bool i_canuse(const unit * u, const item_type * itype)
{
if (itype->canuse) {
return itype->canuse(u, itype);
}
return true;
return rc_can_use(u_race(u), itype);
}
static int

View file

@ -19,6 +19,7 @@ without prior permission by the authors of Eressea.
#include "chaos.h"
#include <kernel/config.h>
#include <kernel/curse.h>
#include <kernel/region.h>
#include <kernel/resources.h>
#include <kernel/unit.h>
@ -29,6 +30,7 @@ without prior permission by the authors of Eressea.
#include <kernel/ship.h>
#include <kernel/plane.h>
#include <kernel/terrain.h>
#include <kernel/messages.h>
#include <modules/autoseed.h>
#include <attributes/key.h>
#include <attributes/racename.h>
@ -46,6 +48,23 @@ without prior permission by the authors of Eressea.
#include <string.h>
#include <stdlib.h>
static int tolua_region_count_msg_type(lua_State *L) {
region *self = (region *)tolua_tousertype(L, 1, 0);
const char *str = tolua_tostring(L, 2, 0);
int n = 0;
if (self->msgs) {
mlist * ml = self->msgs->begin;
while (ml) {
if (strcmp(str, ml->msg->type->name) == 0) {
++n;
}
ml = ml->next;
}
}
lua_pushinteger(L, n);
return 1;
}
int tolua_regionlist_next(lua_State * L)
{
region **region_ptr = (region **)lua_touserdata(L, lua_upvalueindex(1));
@ -341,20 +360,16 @@ static int tolua_region_get_resourcelevel(lua_State * L)
#define LUA_ASSERT(c, s) if (!(c)) { log_error("%s(%d): %s\n", __FILE__, __LINE__, (s)); return 0; }
static critbit_tree * special_resources(void)
{
static critbit_tree cb = CRITBIT_TREE();
if (!cb.root) {
const char * special[] = { "seed", "sapling", "tree", "grave", "chaos", 0 };
char buffer[32];
int i;
for (i = 0; special[i]; ++i) {
size_t len = strlen(special[i]);
len = cb_new_kv(special[i], len, &i, sizeof(int), buffer);
cb_insert(&cb, buffer, len);
static int special_resource(const char *type) {
const char * special[] = { "seed", "sapling", "tree", "grave", "chaos", 0 };
int i;
for (i = 0; special[i]; ++i) {
if (strcmp(type, special[i]) == 0) {
return i;
}
}
return &cb;
return -1;
}
static int tolua_region_get_resource(lua_State * L)
@ -362,32 +377,27 @@ static int tolua_region_get_resource(lua_State * L)
region *r;
const char *type;
const resource_type *rtype;
int result = 0;
void * match;
critbit_tree * cb = special_resources();
int result;
r = (region *)tolua_tousertype(L, 1, 0);
LUA_ASSERT(r != NULL, "invalid parameter");
type = tolua_tostring(L, 2, 0);
LUA_ASSERT(type != NULL, "invalid parameter");
if (cb_find_prefix(cb, type, strlen(type) + 1, &match, 1, 0)) {
cb_get_kv(match, &result, sizeof(result));
switch (result) {
case 0:
case 1:
case 2:
result = rtrees(r, result);
break;
case 3:
result = deathcount(r);
break;
case 4:
result = get_chaoscount(r);
break;
}
}
else {
result = special_resource(type);
switch (result) {
case 0:
case 1:
case 2:
result = rtrees(r, result);
break;
case 3:
result = deathcount(r);
break;
case 4:
result = get_chaoscount(r);
break;
default:
rtype = rt_find(type);
if (rtype) {
result = region_getresource(r, rtype);
@ -406,27 +416,23 @@ static int tolua_region_set_resource(lua_State * L)
region *r = (region *)tolua_tousertype(L, 1, 0);
const char *type = tolua_tostring(L, 2, 0);
int result, value = (int)tolua_tonumber(L, 3, 0);
critbit_tree * cb = special_resources();
void * match;
const resource_type *rtype;
if (cb_find_prefix(cb, type, strlen(type) + 1, &match, 1, 0)) {
cb_get_kv(match, &result, sizeof(result));
switch (result) {
case 0:
case 1:
case 2:
rsettrees(r, result, value);
break;
case 3:
deathcounts(r, value - deathcount(r));
break;
case 4:
add_chaoscount(r, value - get_chaoscount(r));
break;
}
}
else {
const resource_type *rtype = rt_find(type);
result = special_resource(type);
switch (result) {
case 0:
case 1:
case 2:
rsettrees(r, result, value);
break;
case 3:
deathcounts(r, value - deathcount(r));
break;
case 4:
add_chaoscount(r, value - get_chaoscount(r));
break;
default:
rtype = rt_find(type);
if (rtype != NULL) {
region_setresource(r, rtype, value);
}
@ -665,6 +671,27 @@ static int tolua_distance(lua_State * L)
return 1;
}
static int tolua_region_get_curse(lua_State *L) {
region *self = (region *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
if (self->attribs) {
curse * c = get_curse(self->attribs, ct_find(name));
if (c) {
lua_pushnumber(L, curse_geteffect(c));
return 1;
}
}
return 0;
}
static int tolua_region_has_attrib(lua_State *L) {
region *self = (region *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
attrib * a = a_find(self->attribs, at_find(name));
lua_pushboolean(L, a != NULL);
return 1;
}
void tolua_region_open(lua_State * L)
{
/* register user types */
@ -684,6 +711,10 @@ void tolua_region_open(lua_State * L)
tolua_function(L, TOLUA_CAST "destroy", tolua_region_destroy);
tolua_function(L, TOLUA_CAST "__tostring", tolua_region_tostring);
tolua_function(L, TOLUA_CAST "count_msg_type", tolua_region_count_msg_type);
tolua_function(L, TOLUA_CAST "get_curse", &tolua_region_get_curse);
tolua_function(L, TOLUA_CAST "has_attrib", &tolua_region_has_attrib);
/* flags */
tolua_variable(L, TOLUA_CAST "blocked", tolua_region_get_blocked, tolua_region_set_blocked);

View file

@ -16,11 +16,13 @@ without prior permission by the authors of Eressea.
#include "move.h"
#include <kernel/curse.h>
#include <kernel/region.h>
#include <kernel/unit.h>
#include <kernel/ship.h>
#include <kernel/build.h>
#include <util/attrib.h>
#include <util/language.h>
#include <util/log.h>
@ -198,6 +200,27 @@ static int tolua_ship_set_damage(lua_State * L)
return 0;
}
static int tolua_ship_get_curse(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
if (self->attribs) {
curse * c = get_curse(self->attribs, ct_find(name));
if (c) {
lua_pushnumber(L, curse_geteffect(c));
return 1;
}
}
return 0;
}
static int tolua_ship_has_attrib(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
attrib * a = a_find(self->attribs, at_find(name));
lua_pushboolean(L, a != NULL);
return 1;
}
void tolua_ship_open(lua_State * L)
{
/* register user types */
@ -225,6 +248,10 @@ void tolua_ship_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "type", tolua_ship_get_type, 0);
tolua_variable(L, TOLUA_CAST "damage", tolua_ship_get_damage,
tolua_ship_set_damage);
tolua_function(L, TOLUA_CAST "get_curse", &tolua_ship_get_curse);
tolua_function(L, TOLUA_CAST "has_attrib", &tolua_ship_has_attrib);
tolua_function(L, TOLUA_CAST "create", tolua_ship_create);
}
tolua_endmodule(L);

View file

@ -26,6 +26,7 @@ without prior permission by the authors of Eressea.
/* kernel includes */
#include <kernel/building.h>
#include <kernel/config.h>
#include <kernel/curse.h>
#include <kernel/faction.h>
#include <kernel/group.h>
#include <kernel/item.h>
@ -770,6 +771,27 @@ static int tolua_unit_get_orders(lua_State * L)
return 1;
}
static int tolua_unit_get_curse(lua_State *L) {
unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
if (self->attribs) {
curse * c = get_curse(self->attribs, ct_find(name));
if (c) {
lua_pushnumber(L, curse_geteffect(c));
return 1;
}
}
return 0;
}
static int tolua_unit_has_attrib(lua_State *L) {
unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
attrib * a = self->attribs ? a_find(self->attribs, at_find(name)) : NULL;
lua_pushboolean(L, a != NULL);
return 1;
}
static int tolua_unit_get_flag(lua_State * L)
{
unit *self = (unit *)tolua_tousertype(L, 1, 0);
@ -956,6 +978,9 @@ void tolua_unit_open(lua_State * L)
tolua_function(L, TOLUA_CAST "clear_orders", &tolua_unit_clear_orders);
tolua_variable(L, TOLUA_CAST "orders", &tolua_unit_get_orders, 0);
tolua_function(L, TOLUA_CAST "get_curse", &tolua_unit_get_curse);
tolua_function(L, TOLUA_CAST "has_attrib", &tolua_unit_has_attrib);
/* key-attributes for named flags: */
tolua_function(L, TOLUA_CAST "set_flag", &tolua_unit_set_flag);
tolua_function(L, TOLUA_CAST "get_flag", &tolua_unit_get_flag);

View file

@ -480,44 +480,30 @@ static int tolua_write_reports(lua_State * L)
return 1;
}
static void reset_game(void)
{
region *r;
faction *f;
for (r = regions; r; r = r->next) {
unit *u;
building *b;
r->flags &= RF_SAVEMASK;
for (u = r->units; u; u = u->next) {
u->flags &= UFL_SAVEMASK;
}
for (b = r->buildings; b; b = b->next) {
b->flags &= BLD_SAVEMASK;
}
if (r->land && r->land->ownership && r->land->ownership->owner) {
faction *owner = r->land->ownership->owner;
if (owner == get_monsters()) {
/* some compat-fix, i believe. */
owner = update_owners(r);
}
if (owner) {
fset(r, RF_GUARDED);
}
}
}
for (f = factions; f; f = f->next) {
f->flags &= FFL_SAVEMASK;
}
}
static int tolua_process_orders(lua_State * L)
{
++turn;
reset_game();
processorders();
return 0;
}
static int tolua_turn_begin(lua_State * L)
{
turn_begin();
return 0;
}
static int tolua_turn_process(lua_State * L)
{
turn_process();
return 0;
}
static int tolua_turn_end(lua_State * L)
{
turn_end();
return 0;
}
static int tolua_write_passwords(lua_State * L)
{
int result = writepasswd();
@ -1063,6 +1049,9 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile)
tolua_function(L, TOLUA_CAST "factions", tolua_get_factions);
tolua_function(L, TOLUA_CAST "regions", tolua_get_regions);
tolua_function(L, TOLUA_CAST "read_turn", tolua_read_turn);
tolua_function(L, TOLUA_CAST "turn_begin", tolua_turn_begin);
tolua_function(L, TOLUA_CAST "turn_process", tolua_turn_process);
tolua_function(L, TOLUA_CAST "turn_end", tolua_turn_end);
tolua_function(L, TOLUA_CAST "process_orders", tolua_process_orders);
tolua_function(L, TOLUA_CAST "init_reports", tolua_init_reports);
tolua_function(L, TOLUA_CAST "write_reports", tolua_write_reports);

44
src/convert.c Normal file
View file

@ -0,0 +1,44 @@
#include <platform.h>
#ifdef USE_LIBXML2
#include <kernel/xmlreader.h>
#include <util/xml.h>
#endif
#include <kernel/race.h>
#include <kernel/rules.h>
#include <races/races.h>
#include <storage.h>
#include <string.h>
static int usage(void) {
return -1;
}
int main(int argc, char **argv) {
const char *mode;
register_races();
#ifdef USE_LIBXML2
register_xmlreader();
#endif
if (argc < 2) return usage();
mode = argv[1];
#ifdef USE_LIBXML2
if (strcmp(mode, "rules")==0) {
const char *xmlfile, *catalog;
if (argc < 4) return usage();
xmlfile = argv[2];
catalog = argv[3];
read_xml(xmlfile, catalog);
write_rules("rules.dat");
return 0;
}
#endif
if (strcmp(mode, "po")==0) {
return 0;
}
return usage();
}

View file

@ -914,10 +914,6 @@ struct message * get_modifiers(unit *u, const resource_mod *mod, variant *savep,
return NULL;
}
static resource_limit *get_resourcelimit(const resource_type *rtype) {
return rtype->limit;
}
static void allocate_resource(unit * u, const resource_type * rtype, int want)
{
const item_type *itype = resource2item(rtype);
@ -925,7 +921,6 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
int dm = 0;
allocation_list *alist;
allocation *al;
resource_limit *rdata = get_resourcelimit(rtype);
const resource_type *rring;
int amount, skill, skill_mod = 0;
variant save_mod;
@ -934,10 +929,9 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
* Materialverbrauch hat: */
assert(itype != NULL && (itype->construction == NULL
|| itype->construction->materials == NULL));
assert(rdata != NULL);
if (rdata->limit != NULL) {
int avail = rdata->limit(r, rtype);
if (!rtype->raw) {
int avail = limit_resource(r, rtype);
if (avail <= 0) {
cmistake(u, u->thisorder, 121, MSG_PRODUCE);
return;
@ -949,8 +943,8 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
return;
}
if (rdata->modifiers) {
message *msg = get_modifiers(u, rdata->modifiers, &save_mod, &skill_mod);
if (rtype->modifiers) {
message *msg = get_modifiers(u, rtype->modifiers, &save_mod, &skill_mod);
if (msg) {
ADDMSG(&u->faction->msgs, msg);
return;
@ -1122,17 +1116,17 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
{
allocation *al;
int nreq = 0;
resource_limit *rdata = get_resourcelimit(rtype);
int avail = 0;
for (al = alist; al; al = al->next) {
nreq += required(al->want, al->save);
}
if (rdata->limit) {
avail = rdata->limit(r, rtype);
if (avail < 0)
if (!rtype->raw) {
avail = limit_resource(r, rtype);
if (avail < 0) {
avail = 0;
}
}
avail = MIN(avail, nreq);
@ -1147,10 +1141,11 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
nreq -= want;
al->get = x * al->save.sa[0] / al->save.sa[1];
al->get = MIN(al->want, al->get);
if (rdata->produce) {
if (!rtype->raw) {
int use = required(al->get, al->save);
if (use)
rdata->produce(r, rtype, use);
if (use) {
produce_resource(r, rtype, use);
}
}
}
}
@ -1162,15 +1157,10 @@ typedef void(*allocate_function) (const resource_type *, struct region *,
static allocate_function get_allocator(const struct resource_type *rtype)
{
resource_limit *rdata = get_resourcelimit(rtype);
if (rdata) {
if (rdata->limit != NULL) {
return attrib_allocation;
}
if (rtype->raw) {
return leveled_allocation;
}
return NULL;
return attrib_allocation;
}
void split_allocations(region * r)

View file

@ -348,7 +348,6 @@ static void test_make_item(CuTest *tc) {
struct item_type *itype;
const struct resource_type *rt_silver;
resource_type *rtype;
resource_limit *rdata;
double d = 0.6;
test_setup();
@ -382,7 +381,6 @@ static void test_make_item(CuTest *tc) {
itype->construction->materials = 0;
rtype->flags |= RTF_LIMITED;
rmt_create(rtype);
rdata = rtype->limit = calloc(1, sizeof(resource_limit));
add_resource(u->region, 1, 300, 150, rtype);
u->region->resources->amount = 300; /* there are 300 stones at level 1 */
set_level(u, SK_ALCHEMY, 10);
@ -392,11 +390,11 @@ static void test_make_item(CuTest *tc) {
CuAssertIntEquals(tc, 11, get_item(u, itype));
CuAssertIntEquals(tc, 290, u->region->resources->amount); /* used 10 stones to make 10 stones */
rdata->modifiers = calloc(2, sizeof(resource_mod));
rdata->modifiers[0].flags = RMF_SAVEMATERIAL;
rdata->modifiers[0].race = u->_race;
rdata->modifiers[0].value.sa[0] = (short)(0.5+100*d);
rdata->modifiers[0].value.sa[1] = 100;
rtype->modifiers = calloc(2, sizeof(resource_mod));
rtype->modifiers[0].flags = RMF_SAVEMATERIAL;
rtype->modifiers[0].race = u->_race;
rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d);
rtype->modifiers[0].value.sa[1] = 100;
make_item(u, itype, 10);
split_allocations(u->region);
CuAssertIntEquals(tc, 21, get_item(u, itype));
@ -407,9 +405,9 @@ static void test_make_item(CuTest *tc) {
CuAssertIntEquals(tc, 22, get_item(u, itype));
CuAssertIntEquals(tc, 283, u->region->resources->amount); /* no free lunches */
rdata->modifiers[0].flags = RMF_REQUIREDBUILDING;
rdata->modifiers[0].race = NULL;
rdata->modifiers[0].btype = bt_get_or_create("mine");
rtype->modifiers[0].flags = RMF_REQUIREDBUILDING;
rtype->modifiers[0].race = NULL;
rtype->modifiers[0].btype = bt_get_or_create("mine");
make_item(u, itype, 10);
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104"));

View file

@ -8,9 +8,6 @@
#if MUSEUM_MODULE
#include <modules/museum.h>
#endif
#if ARENA_MODULE
#include <modules/arena.h>
#endif
#include <triggers/triggers.h>
#include <util/language.h>
#include <util/functions.h>
@ -77,9 +74,6 @@ void game_init(void)
register_itemfunctions();
#if MUSEUM_MODULE
register_museum();
#endif
#if ARENA_MODULE
register_arena();
#endif
wormholes_register();

View file

@ -19,6 +19,7 @@
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/build.h>
#include <kernel/curse.h>
#include <kernel/faction.h>
#include <kernel/item.h>
@ -147,17 +148,35 @@ int give_quota(const unit * src, const unit * dst, const item_type * type,
return n;
}
static void
give_horses(unit * s, const item_type * itype, int n)
{
region *r = s->region;
if (r->land) {
rsethorses(r, rhorses(r) + n);
}
}
static void
give_money(unit * s, const item_type * itype, int n)
{
region *r = s->region;
if (r->land) {
rsetmoney(r, rmoney(r) + n);
}
}
int
give_item(int want, const item_type * itype, unit * src, unit * dest,
struct order *ord)
{
short error = 0;
int n, r;
int n, delta;
assert(itype != NULL);
n = get_pooled(src, item2resource(itype), GET_SLACK | GET_POOLED_SLACK, want);
n = MIN(want, n);
r = n;
delta = n;
if (dest && src->faction != dest->faction
&& src->faction->age < GiveRestriction()) {
if (ord != NULL) {
@ -178,18 +197,19 @@ struct order *ord)
else if (itype->flags & ITF_CURSED) {
error = 25;
}
else if (itype->give == NULL || itype->give(src, dest, itype, n, ord) != 0) {
else {
int use = use_pooled(src, item2resource(itype), GET_SLACK, n);
if (use < n)
use +=
use_pooled(src, item2resource(itype), GET_POOLED_SLACK,
n - use);
if (dest) {
r = give_quota(src, dest, itype, n);
i_change(&dest->items, itype, r);
delta = give_quota(src, dest, itype, n);
i_change(&dest->items, itype, delta);
#ifdef RESERVE_GIVE
#ifdef RESERVE_DONATIONS
change_reservation(dest, itype, r);
change_reservation(dest, itype, delta);
#else
if (src->faction == dest->faction) {
change_reservation(dest, item2resource(itype), r);
@ -199,14 +219,25 @@ struct order *ord)
#if MUSEUM_MODULE && defined(TODO)
/* TODO: use a trigger for the museum warden! */
if (a_find(dest->attribs, &at_warden)) {
warden_add_give(src, dest, itype, r);
warden_add_give(src, dest, itype, delta);
}
#endif
handle_event(dest->attribs, "receive", src);
}
else {
/* return horses to the region */
if (itype->construction && itype->flags & ITF_ANIMAL) {
if (itype->construction->skill == SK_HORSE_TRAINING) {
give_horses(src, itype, n);
}
}
else if (itype->rtype == get_resourcetype(R_SILVER)) {
give_money(src, itype, n);
}
}
handle_event(src->attribs, "give", dest);
}
add_give(src, dest, n, r, item2resource(itype), ord, error);
add_give(src, dest, n, delta, item2resource(itype), ord, error);
if (error)
return -1;
return 0;

View file

@ -26,9 +26,6 @@
#if MUSEUM_MODULE
#include <modules/museum.h>
#endif
#if ARENA_MODULE
#include <modules/arena.h>
#endif
#include <modules/autoseed.h>
#include <kernel/building.h>

View file

@ -13,6 +13,7 @@ without prior permission by the authors of Eressea.
#include <platform.h>
#include "helpers.h"
#include "vortex.h"
#include "alchemy.h"
#include <util/attrib.h>
#include <util/base36.h>
@ -27,6 +28,7 @@ without prior permission by the authors of Eressea.
#include <kernel/faction.h>
#include <kernel/spell.h>
#include <kernel/race.h>
#include <kernel/resources.h>
#include <kernel/unit.h>
#include <kernel/building.h>
#include <kernel/item.h>
@ -78,7 +80,7 @@ lua_giveitem(unit * s, unit * d, const item_type * itype, int n, struct order *o
return result;
}
static int limit_resource(const region * r, const resource_type * rtype)
static int limit_resource_lua(const region * r, const resource_type * rtype)
{
char fname[64];
int result = -1;
@ -110,7 +112,7 @@ static int limit_resource(const region * r, const resource_type * rtype)
}
static void
produce_resource(region * r, const resource_type * rtype, int norders)
produce_resource_lua(region * r, const resource_type * rtype, int norders)
{
lua_State *L = (lua_State *)global.vm_state;
char fname[64];
@ -318,34 +320,6 @@ static int lua_getresource(unit * u, const struct resource_type *rtype)
return result;
}
static bool lua_canuse_item(const unit * u, const struct item_type *itype)
{
bool result = true;
lua_State *L = (lua_State *)global.vm_state;
const char *fname = "item_canuse";
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
tolua_pushstring(L, itype->rtype->_name);
if (lua_pcall(L, 2, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error);
lua_pop(L, 1);
}
else {
result = lua_toboolean(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
static int
lua_wage(const region * r, const faction * f, const race * rc, int in_turn)
{
@ -489,17 +463,22 @@ static int lua_equipmentcallback(const struct equipment *eq, unit * u)
}
/** callback for an item-use function written in lua. */
int
lua_useitem(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
static int
use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
{
lua_State *L = (lua_State *)global.vm_state;
int result = 0;
char fname[64];
int (*callout)(unit *, const item_type *, int, struct order *);
strlcpy(fname, "use_", sizeof(fname));
strlcat(fname, itype->rtype->_name, sizeof(fname));
callout = (int(*)(unit *, const item_type *, int, struct order *))get_function(fname);
if (callout) {
return callout(u, itype, amount, ord);
}
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
@ -515,11 +494,15 @@ struct order *ord)
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
return result;
}
else {
log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
lua_pop(L, 1);
lua_pop(L, 1);
if (itype->rtype->ptype) {
return use_potion(u, itype, amount, ord);
} else {
log_error("no such callout: %s", fname);
}
log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
return result;
}
@ -550,11 +533,8 @@ void register_tolua_helpers(void)
register_function((pf_generic)lua_callspell, TOLUA_CAST "lua_castspell");
register_function((pf_generic)lua_initfamiliar,
TOLUA_CAST "lua_initfamiliar");
register_item_use(&lua_useitem, TOLUA_CAST "lua_useitem");
register_function((pf_generic)lua_getresource,
TOLUA_CAST "lua_getresource");
register_function((pf_generic)lua_canuse_item,
TOLUA_CAST "lua_canuse_item");
register_function((pf_generic)lua_changeresource,
TOLUA_CAST "lua_changeresource");
register_function((pf_generic)lua_equipmentcallback,
@ -564,9 +544,8 @@ void register_tolua_helpers(void)
register_function((pf_generic)lua_maintenance,
TOLUA_CAST "lua_maintenance");
register_function((pf_generic)produce_resource,
TOLUA_CAST "lua_produceresource");
register_function((pf_generic)limit_resource,
TOLUA_CAST "lua_limitresource");
item_use_fun = use_item_lua;
res_produce_fun = produce_resource_lua;
res_limit_fun = limit_resource_lua;
register_item_give(lua_giveitem, TOLUA_CAST "lua_giveitem");
}

View file

@ -1,6 +1,7 @@
#include <platform.h>
#include "items.h"
#include "alchemy.h"
#include "study.h"
#include "economy.h"
#include "move.h"
@ -14,16 +15,24 @@
#include <kernel/order.h>
#include <kernel/plane.h>
#include <kernel/pool.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/ship.h>
#include <kernel/spell.h>
#include <kernel/unit.h>
#include <items/demonseye.h>
#include <attributes/fleechance.h>
/* triggers includes */
#include <triggers/changerace.h>
#include <triggers/timeout.h>
#include <util/attrib.h>
#include <util/event.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/rand.h>
#include <util/rng.h>
#include <assert.h>
#include <limits.h>
@ -34,7 +43,7 @@ static int
use_studypotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
if (init_order(u->thisorder) == K_STUDY) {
if (u->thisorder && init_order(u->thisorder) == K_STUDY) {
char token[128];
skill_t sk = NOSKILL;
skill *sv = 0;
@ -61,9 +70,9 @@ struct order *ord)
if (amount > MAXGAIN) {
amount = MAXGAIN;
}
teach->value += amount * 30;
if (teach->value > MAXGAIN * 30) {
teach->value = MAXGAIN * 30;
teach->value += amount * STUDYDAYS;
if (teach->value > MAXGAIN * STUDYDAYS) {
teach->value = MAXGAIN * STUDYDAYS;
}
i_change(&u->items, itype, -amount);
return 0;
@ -71,7 +80,6 @@ struct order *ord)
}
return EUNUSABLE;
}
/* END studypotion */
/* BEGIN speedsail */
@ -89,9 +97,8 @@ struct order *ord)
}
effect = SPEEDSAIL_EFFECT;
c =
create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, effect,
0);
c = create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX,
effect, 0);
c_setflag(c, CURSE_NOAGE);
ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u,
@ -125,15 +132,15 @@ struct order *ord)
UNUSED_ARG(ord);
assert(sp);
/* Reduziert die Stärke jedes Spruchs um effect */
/* Reduziert die St<EFBFBD>rke jedes Spruchs um effect */
effect = 5;
/* Hält Sprüche bis zu einem summierten Gesamtlevel von power aus.
/* H<EFBFBD>lt Spr<70>che bis zu einem summierten Gesamtlevel von power aus.
* Jeder Zauber reduziert die 'Lebenskraft' (vigour) der Antimagiezone
* um seine Stufe */
force = effect * 20; /* Stufe 5 =~ 100 */
/* Regionszauber auflösen */
/* Regionszauber aufl<EFBFBD>sen */
while (*ap && force > 0) {
curse *c;
attrib *a = *ap;
@ -145,7 +152,7 @@ struct order *ord)
}
c = (curse *)a->data.v;
/* Immunität prüfen */
/* Immunit<EFBFBD>t pr<70>fen */
if (c_flags(c) & CURSE_IMMUNE) {
do {
ap = &(*ap)->next;
@ -171,50 +178,6 @@ struct order *ord)
return 0;
}
static int
use_instantartsculpture(struct unit *u, const struct item_type *itype,
int amount, struct order *ord)
{
building *b;
if (u->region->land == NULL) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", ""));
return -1;
}
b = new_building(bt_find("artsculpture"), u->region, u->faction->locale);
b->size = 100;
ADDMSG(&u->region->msgs, msg_message("artsculpture_create", "unit region",
u, u->region));
use_pooled(u, itype->rtype, GET_DEFAULT, 1);
return 0;
}
static int
use_instantartacademy(struct unit *u, const struct item_type *itype,
int amount, struct order *ord)
{
building *b;
if (u->region->land == NULL) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", ""));
return -1;
}
b = new_building(bt_find("artacademy"), u->region, u->faction->locale);
b->size = 100;
ADDMSG(&u->region->msgs, msg_message("artacademy_create", "unit region", u,
u->region));
use_pooled(u, itype->rtype, GET_DEFAULT, 1);
return 0;
}
#define BAGPIPEFRACTION dice_rand("2d4+2")
#define BAGPIPEDURATION dice_rand("2d10+4")
@ -264,14 +227,204 @@ int amount, struct order *ord)
return 0;
}
static int
use_birthdayamulet(unit * u, const struct item_type *itype, int amount,
struct order *ord)
{
direction_t d;
message *msg = msg_message("meow", "");
UNUSED_ARG(ord);
UNUSED_ARG(amount);
UNUSED_ARG(itype);
add_message(&u->region->msgs, msg);
for (d = 0; d < MAXDIRECTIONS; d++) {
region *tr = rconnect(u->region, d);
if (tr)
add_message(&tr->msgs, msg);
}
msg_release(msg);
return 0;
}
static int use_foolpotion(unit *u, const item_type *itype, int amount,
struct order *ord)
{
int targetno = read_unitid(u->faction, u->region);
unit *target = findunit(targetno);
if (target == NULL || u->region != target->region) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
""));
return ECUSTOM;
}
if (effskill(u, SK_STEALTH, 0) <= effskill(target, SK_PERCEPTION, 0)) {
cmistake(u, ord, 64, MSG_EVENT);
return ECUSTOM;
}
ADDMSG(&u->faction->msgs, msg_message("givedumb",
"unit recipient amount", u, target, amount));
change_effect(target, itype->rtype->ptype, amount);
use_pooled(u, itype->rtype, GET_DEFAULT, amount);
return 0;
}
static int
use_bloodpotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) {
change_effect(u, itype->rtype->ptype, 100 * amount);
}
else {
const race *irace = u_irace(u);
if (irace == u_race(u)) {
const race *rcfailure = rc_find("smurf");
if (!rcfailure) {
rcfailure = rc_find("toad");
}
if (rcfailure) {
trigger *trestore = trigger_changerace(u, u_race(u), irace);
if (trestore) {
int duration = 2 + rng_int() % 8;
add_trigger(&u->attribs, "timer", trigger_timeout(duration,
trestore));
u->irace = NULL;
u_setrace(u, rcfailure);
}
}
}
}
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0;
}
static int heal(unit * user, int effect)
{
int req = unit_max_hp(user) * user->number - user->hp;
if (req > 0) {
req = MIN(req, effect);
effect -= req;
user->hp += req;
}
return effect;
}
static int
use_healingpotion(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
int effect = amount * 400;
unit *u = user->region->units;
effect = heal(user, effect);
while (effect > 0 && u != NULL) {
if (u->faction == user->faction) {
effect = heal(u, effect);
}
u = u->next;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(user, itype->rtype->ptype);
ADDMSG(&user->faction->msgs, msg_message("usepotion",
"unit potion", user, itype->rtype));
return 0;
}
/* ------------------------------------------------------------- */
/* Kann auch von Nichtmagier benutzt werden, modifiziert Taktik fuer diese
* Runde um -1 - 4 Punkte. */
static int
use_tacticcrystal(unit * u, const struct item_type *itype, int amount,
struct order *ord)
{
int i;
for (i = 0; i != amount; ++i) {
int duration = 1; /* wirkt nur in dieser Runde */
curse *c;
float effect;
float power = 5; /* Widerstand gegen Antimagiesprueche, ist in diesem
Fall egal, da der curse fuer den Kampf gelten soll,
der vor den Antimagiezaubern passiert */
effect = (float)(rng_int() % 6 - 1);
c = create_curse(u, &u->attribs, ct_find("skillmod"), power,
duration, effect, u->number);
c->data.i = SK_TACTICS;
UNUSED_ARG(ord);
}
use_pooled(u, itype->rtype, GET_DEFAULT, amount);
ADDMSG(&u->faction->msgs, msg_message("use_tacticcrystal",
"unit region", u, u->region));
return 0;
}
static int
use_mistletoe(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
int mtoes =
get_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
if (user->number > mtoes) {
ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
"unit item region command", user, itype->rtype, user->region, ord));
return -1;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
a_add(&user->attribs, make_fleechance((float)1.0));
ADDMSG(&user->faction->msgs,
msg_message("use_item", "unit item", user, itype->rtype));
return 0;
}
static int use_warmthpotion(unit *u, const item_type *itype,
int amount, struct order *ord)
{
if (u->faction->race == get_race(RC_INSECT)) {
u->flags |= UFL_WARMTH;
}
else {
/* nur fuer insekten: */
cmistake(u, ord, 163, MSG_EVENT);
return ECUSTOM;
}
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0;
}
void register_itemfunctions(void)
{
register_demonseye();
register_item_use(use_antimagiccrystal, "use_antimagiccrystal");
register_item_use(use_instantartsculpture, "use_instantartsculpture");
/* have tests: */
register_item_use(use_mistletoe, "use_mistletoe");
register_item_use(use_tacticcrystal, "use_dreameye");
register_item_use(use_studypotion, "use_studypotion");
register_item_use(use_antimagiccrystal, "use_antimagic");
register_item_use(use_speedsail, "use_speedsail");
register_item_use(use_instantartacademy, "use_instantartacademy");
register_item_use(use_bagpipeoffear, "use_bagpipeoffear");
register_item_use(use_aurapotion50, "use_aurapotion50");
register_item_use(use_birthdayamulet, "use_aoc");
register_item_use(use_foolpotion, "use_p7");
register_item_use(use_bloodpotion, "use_peasantblood");
register_item_use(use_healingpotion, "use_ointment");
register_item_use(use_warmthpotion, "use_nestwarmth");
/* ungetestet: Wasser des Lebens */
register_item_use(use_potion_delayed, "use_p2");
}

View file

@ -5,7 +5,6 @@ xerewards.test.c
)
SET(_FILES
demonseye.c
speedsail.c
weapons.c
xerewards.c

View file

@ -1,65 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#include <platform.h>
#include "demonseye.h"
/* kernel includes */
#include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/messages.h>
#include <kernel/plane.h>
#include <kernel/region.h>
#include <kernel/unit.h>
/* util includes */
#include <util/functions.h>
/* libc includes */
#include <assert.h>
static int
summon_igjarjuk(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
struct plane *p = rplane(u->region);
UNUSED_ARG(amount);
UNUSED_ARG(itype);
if (p != NULL) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "use_realworld_only", ""));
return EUNUSABLE;
}
else {
assert(!"not implemented");
return EUNUSABLE;
}
}
static int
give_igjarjuk(struct unit *src, struct unit *d, const struct item_type *itype,
int n, struct order *ord)
{
ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "error_giveeye", ""));
return 0;
}
void register_demonseye(void)
{
register_item_use(summon_igjarjuk, "useigjarjuk");
register_item_give(give_igjarjuk, "giveigjarjuk");
}

View file

@ -1,30 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#ifndef H_ITM_DEMONSEYE
#define H_ITM_DEMONSEYE
#ifdef __cplusplus
extern "C" {
#endif
void register_demonseye(void);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -54,6 +54,7 @@ pool.c
race.c
region.c
resources.c
rules.c
save.c
ship.c
skills.c

View file

@ -34,23 +34,18 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "terrain.h"
#include "unit.h"
/* triggers includes */
#include <triggers/changerace.h>
#include <triggers/timeout.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <critbit.h>
#include <util/event.h>
#include <util/functions.h>
#include <util/goodies.h>
#include <util/log.h>
#include <util/language.h>
#include <util/message.h>
#include <util/umlaut.h>
#include <util/rng.h>
#include <util/umlaut.h>
#include <critbit.h>
#include <storage.h>
/* libc includes */
@ -570,46 +565,6 @@ item *i_new(const item_type * itype, int size)
#include "region.h"
static int
give_horses(unit * s, unit * d, const item_type * itype, int n,
struct order *ord)
{
if (d == NULL) {
int use = use_pooled(s, item2resource(itype), GET_SLACK, n);
region *r = s->region;
if (use < n) {
use +=
use_pooled(s, item2resource(itype), GET_RESERVE | GET_POOLED_SLACK,
n - use);
}
if (r->land) {
rsethorses(r, rhorses(r) + use);
}
return 0;
}
return -1; /* use the mechanism */
}
static int
give_money(unit * s, unit * d, const item_type * itype, int n,
struct order *ord)
{
if (d == NULL) {
int use = use_pooled(s, item2resource(itype), GET_SLACK, n);
region *r = s->region;
if (use < n) {
use +=
use_pooled(s, item2resource(itype), GET_RESERVE | GET_POOLED_SLACK,
n - use);
}
if (r->land) {
rsetmoney(r, rmoney(r) + use);
}
return 0;
}
return -1; /* use the mechanism */
}
#define R_MINOTHER R_SILVER
#define R_MINHERB R_PLAIN_1
#define R_MINPOTION R_FAST
@ -675,27 +630,6 @@ int set_item(unit * u, const item_type *itype, int value)
return value;
}
static int
use_birthdayamulet(unit * u, const struct item_type *itype, int amount,
struct order *ord)
{
direction_t d;
message *msg = msg_message("meow", "");
UNUSED_ARG(ord);
UNUSED_ARG(amount);
UNUSED_ARG(itype);
add_message(&u->region->msgs, msg);
for (d = 0; d < MAXDIRECTIONS; d++) {
region *tr = rconnect(u->region, d);
if (tr)
add_message(&tr->msgs, msg);
}
msg_release(msg);
return 0;
}
/* t_item::flags */
#define FL_ITEM_CURSED (1<<0)
#define FL_ITEM_NOTLOST (1<<1)
@ -703,34 +637,6 @@ struct order *ord)
#define FL_ITEM_ANIMAL (1<<3) /* ist ein Tier */
#define FL_ITEM_MOUNT ((1<<4) | FL_ITEM_ANIMAL) /* ist ein Reittier */
/* ------------------------------------------------------------- */
/* Kann auch von Nichtmagier benutzt werden, modifiziert Taktik fuer diese
* Runde um -1 - 4 Punkte. */
static int
use_tacticcrystal(unit * u, const struct item_type *itype, int amount,
struct order *ord)
{
int i;
for (i = 0; i != amount; ++i) {
int duration = 1; /* wirkt nur eine Runde */
curse *c;
float effect;
float power = 5; /* Widerstand gegen Antimagiesprueche, ist in diesem
Fall egal, da der curse fuer den Kampf gelten soll,
der vor den Antimagiezaubern passiert */
effect = (float)(rng_int() % 6 - 1);
c = create_curse(u, &u->attribs, ct_find("skillmod"), power,
duration, effect, u->number);
c->data.i = SK_TACTICS;
UNUSED_ARG(ord);
}
use_pooled(u, itype->rtype, GET_DEFAULT, amount);
ADDMSG(&u->faction->msgs, msg_message("use_tacticcrystal",
"unit region", u, u->region));
return 0;
}
typedef struct t_item {
const char *name;
/* [0]: Einzahl fuer eigene; [1]: Mehrzahl fuer eigene;
@ -766,17 +672,6 @@ mod_dwarves_only(const unit * u, const region * r, skill_t sk, int value)
return -118;
}
static int heal(unit * user, int effect)
{
int req = unit_max_hp(user) * user->number - user->hp;
if (req > 0) {
req = MIN(req, effect);
effect -= req;
user->hp += req;
}
return effect;
}
void
register_item_give(int(*foo) (struct unit *, struct unit *,
const struct item_type *, int, struct order *), const char *name)
@ -791,173 +686,6 @@ struct order *), const char *name)
register_function((pf_generic)foo, name);
}
void
register_item_useonother(int(*foo) (struct unit *, int,
const struct item_type *, int, struct order *), const char *name)
{
register_function((pf_generic)foo, name);
}
static int
use_healingpotion(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
int effect = amount * 400;
unit *u = user->region->units;
effect = heal(user, effect);
while (effect > 0 && u != NULL) {
if (u->faction == user->faction) {
effect = heal(u, effect);
}
u = u->next;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(user, itype->rtype->ptype);
ADDMSG(&user->faction->msgs, msg_message("usepotion",
"unit potion", user, itype->rtype));
return 0;
}
static int
use_warmthpotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
if (u->faction->race == get_race(RC_INSECT)) {
fset(u, UFL_WARMTH);
}
else {
/* nur fuer insekten: */
cmistake(u, ord, 163, MSG_EVENT);
return ECUSTOM;
}
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0;
}
static int
use_foolpotion(struct unit *u, int targetno, const struct item_type *itype,
int amount, struct order *ord)
{
unit *target = findunit(targetno);
if (target == NULL || u->region != target->region) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
""));
return ECUSTOM;
}
if (effskill(u, SK_STEALTH, 0) <= effskill(target, SK_PERCEPTION, 0)) {
cmistake(u, ord, 64, MSG_EVENT);
return ECUSTOM;
}
ADDMSG(&u->faction->msgs, msg_message("givedumb",
"unit recipient amount", u, target, amount));
change_effect(target, itype->rtype->ptype, amount);
use_pooled(u, itype->rtype, GET_DEFAULT, amount);
return 0;
}
static int
use_bloodpotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) {
change_effect(u, itype->rtype->ptype, 100 * amount);
}
else {
const race *irace = u_irace(u);
if (irace == u_race(u)) {
const race *rcfailure = rc_find("smurf");
if (!rcfailure) {
rcfailure = rc_find("toad");
}
if (rcfailure) {
trigger *trestore = trigger_changerace(u, u_race(u), irace);
if (trestore) {
int duration = 2 + rng_int() % 8;
add_trigger(&u->attribs, "timer", trigger_timeout(duration,
trestore));
u->irace = NULL;
u_setrace(u, rcfailure);
}
}
}
}
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0;
}
#include <attributes/fleechance.h>
static int
use_mistletoe(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
int mtoes =
get_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
if (user->number > mtoes) {
ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
"unit item region command", user, itype->rtype, user->region, ord));
return -1;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
a_add(&user->attribs, make_fleechance((float)1.0));
ADDMSG(&user->faction->msgs,
msg_message("use_item", "unit item", user, itype->rtype));
return 0;
}
static int
use_magicboost(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
int mtoes =
get_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
faction *f = user->faction;
if (user->number > mtoes) {
ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
"unit item region command", user, itype->rtype, user->region, ord));
return -1;
}
if (!is_mage(user) || key_get(f->attribs, atoi36("mbst"))) {
cmistake(user, user->thisorder, 214, MSG_EVENT);
return -1;
}
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
user->number);
key_set(&f->attribs, atoi36("mbst"), turn);
set_level(user, SK_MAGIC, 3);
ADDMSG(&user->faction->msgs, msg_message("use_item",
"unit item", user, itype->rtype));
return 0;
}
static int
use_snowball(struct unit *user, const struct item_type *itype, int amount,
struct order *ord)
{
return 0;
}
static void init_oldpotions(void)
{
const char *potionnames[MAX_POTIONS] = {
@ -987,7 +715,6 @@ void init_resources(void)
rtype->flags |= RTF_ITEM | RTF_POOLED;
rtype->uchange = res_changeitem;
rtype->itype = it_get_or_create(rtype);
rtype->itype->give = give_money;
rtype = rt_get_or_create(resourcenames[R_PERMAURA]);
rtype->uchange = res_changepermaura;
@ -1236,15 +963,12 @@ void free_rtype(resource_type *rtype) {
if (rtype->wtype) {
free_wtype(rtype->wtype);
}
if (rtype->atype) {
free(rtype->atype);
}
if (rtype->itype) {
free_itype(rtype->itype);
}
if (rtype->raw) {
free(rtype->raw);
}
free(rtype->atype);
free(rtype->modifiers);
free(rtype->raw);
free(rtype->_name);
free(rtype);
}
@ -1290,18 +1014,4 @@ void register_resources(void)
register_function((pf_generic)res_changepermaura, "changepermaura");
register_function((pf_generic)res_changehp, "changehp");
register_function((pf_generic)res_changeaura, "changeaura");
register_item_use(use_potion, "usepotion");
register_item_use(use_potion_delayed, "usepotion_delayed");
register_item_use(use_tacticcrystal, "use_tacticcrystal");
register_item_use(use_birthdayamulet, "use_birthdayamulet");
register_item_use(use_warmthpotion, "usewarmthpotion");
register_item_use(use_bloodpotion, "usebloodpotion");
register_item_use(use_healingpotion, "usehealingpotion");
register_item_useonother(use_foolpotion, "usefoolpotion");
register_item_use(use_mistletoe, "usemistletoe");
register_item_use(use_magicboost, "usemagicboost");
register_item_use(use_snowball, "usesnowball");
register_item_give(give_horses, "givehorses");
}

View file

@ -39,7 +39,7 @@ extern "C" {
struct storage;
struct gamedata;
struct rawmaterial_type;
struct resource_limit;
struct resource_mod;
typedef struct item {
struct item *next;
@ -68,8 +68,6 @@ extern "C" {
typedef int(*rtype_uchange) (struct unit * user,
const struct resource_type * rtype, int delta);
typedef int(*rtype_uget) (const struct unit * user,
const struct resource_type * rtype);
typedef char *(*rtype_name) (const struct resource_type * rtype, int flags);
typedef struct resource_type {
/* --- constants --- */
@ -77,10 +75,9 @@ extern "C" {
unsigned int flags;
/* --- functions --- */
rtype_uchange uchange;
rtype_uget uget;
rtype_name name;
struct rawmaterial_type *raw;
struct resource_limit *limit;
struct resource_mod *modifiers;
/* --- pointers --- */
struct attrib *attribs;
struct item_type *itype;
@ -107,6 +104,7 @@ extern "C" {
#define ITF_BIG 0x0008 /* big item, e.g. does not fit in a bag of holding */
#define ITF_ANIMAL 0x0010 /* an animal */
#define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */
#define ITF_CANUSE 0x0040 /* can be used with use_item_fun callout */
/* error codes for item_type::use */
#define ECUSTOM -1
@ -120,17 +118,10 @@ extern "C" {
unsigned int flags;
int weight;
int capacity;
int mask_allow;
int mask_deny;
struct construction *construction;
char *_appearance[2]; /* wie es f<>r andere aussieht */
/* --- functions --- */
bool(*canuse) (const struct unit * user,
const struct item_type * itype);
int(*use) (struct unit * user, const struct item_type * itype, int amount,
struct order * ord);
int(*useonother) (struct unit * user, int targetno,
const struct item_type * itype, int amount, struct order * ord);
int(*give) (struct unit * src, struct unit * dest,
const struct item_type * itm, int number, struct order * ord);
int score;
} item_type;
@ -311,8 +302,6 @@ extern "C" {
const struct item_type *, int, struct order *), const char *name);
void register_item_use(int(*foo) (struct unit *,
const struct item_type *, int, struct order *), const char *name);
void register_item_useonother(int(*foo) (struct unit *, int,
const struct item_type *, int, struct order *), const char *name);
void free_resources(void);

View file

@ -162,7 +162,6 @@ static void test_core_resources(CuTest *tc) {
CuAssertPtrNotNull(tc, rtype = rt_find("money"));
CuAssertPtrNotNull(tc, rtype->itype);
CuAssertPtrNotNull(tc, rtype->uchange);
CuAssertPtrNotNull(tc, rtype->itype->give);
CuAssertPtrNotNull(tc, rtype = rt_find("peasant"));
CuAssertPtrEquals(tc, 0, rtype->itype);
CuAssertPtrNotNull(tc, rtype = rt_find("person"));

View file

@ -40,11 +40,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
int get_resource(const unit * u, const resource_type * rtype)
{
assert(rtype);
if (rtype->uget) {
/* this resource is probably special */
int i = rtype->uget(u, rtype);
if (i >= 0)
return i;
if (rtype == get_resourcetype(R_PEASANT)) {
return u->region->land ? u->region->land->peasants : 0;
}
else if (rtype == rt_find("hp")) {
return u->hp;
}
else if (rtype->uchange) {
/* this resource is probably special */
@ -176,7 +176,7 @@ int count)
}
if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK | GET_RESERVE)) {
for (v = r->units; v && use < count; v = v->next)
if (u != v && (v->items || rtype->uget)) {
if (u != v) {
int mask;
if ((u_race(v)->ec_flags & ECF_KEEP_ITEM))
@ -234,8 +234,6 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count)
int mask;
if ((u_race(v)->ec_flags & ECF_KEEP_ITEM))
continue;
if (v->items == NULL && rtype->uget == NULL)
continue;
if (v->faction == f) {
mask = (mode >> 3) & (GET_SLACK | GET_RESERVE);

View file

@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@ -94,6 +95,7 @@ enum {
RCO_TRADEHERB
};
static void rc_setoption(race *rc, int k, const char *value) {
unsigned char key = (unsigned char)k;
int i;
@ -323,6 +325,17 @@ bool rc_changed(int *cache) {
return false;
}
bool rc_can_use(const struct race *rc, const struct item_type *itype)
{
if (itype->mask_allow) {
return (itype->mask_allow & rc->mask_item) != 0;
}
if (itype->mask_deny) {
return (itype->mask_deny & rc->mask_item) == 0;
}
return true;
}
race *rc_create(const char *zName)
{
race *rc;

View file

@ -48,6 +48,7 @@ extern "C" {
struct spellref;
struct locale;
struct rcoption;
struct item_type;
extern int num_races;
@ -140,6 +141,7 @@ extern "C" {
int flags;
int battle_flags;
int ec_flags;
int mask_item;
struct att attack[RACE_ATTACKS];
signed char bonus[MAXSKILLS];
@ -174,6 +176,8 @@ extern "C" {
const race *rc_find(const char *);
void free_races(void);
bool rc_can_use(const struct race *rc, const struct item_type *itype);
typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t;
const char * rc_name_s(const race *rc, name_t n);
const char * rc_name(const race *rc, name_t n, char *name, size_t size);

View file

@ -1,10 +1,13 @@
#include <platform.h>
#include <kernel/config.h>
#include "race.h"
#include <CuTest.h>
#include "item.h"
#include <tests.h>
#include <CuTest.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
static void test_rc_name(CuTest *tc) {
@ -100,6 +103,54 @@ static void test_rc_set_param(CuTest *tc) {
test_cleanup();
}
static void test_rc_can_use(CuTest *tc) {
race *rc;
item_type *itype;
test_setup();
rc = test_create_race("goblin");
itype = test_create_itemtype("plate");
CuAssertTrue(tc, rc_can_use(rc, itype));
/* default case. all items and races in E2 */
itype->mask_deny = 0;
rc->mask_item = 0;
CuAssertTrue(tc, rc_can_use(rc, itype));
/* some race is forbidden from using this item. */
itype->mask_deny = 1;
/* we are not that race. */
rc->mask_item = 2;
CuAssertTrue(tc, rc_can_use(rc, itype));
/* we are that race */
rc->mask_item = 1;
CuAssertTrue(tc, ! rc_can_use(rc, itype));
/* we are not a special race at all */
rc->mask_item = 0;
CuAssertTrue(tc, rc_can_use(rc, itype));
/* only one race is allowed to use this item */
itype->mask_deny = 0;
itype->mask_allow = 1;
/* we are not that race */
rc->mask_item = 2;
CuAssertTrue(tc, ! rc_can_use(rc, itype));
/* we are that race */
rc->mask_item = 1;
CuAssertTrue(tc, rc_can_use(rc, itype));
/* we are not special */
rc->mask_item = 0;
CuAssertTrue(tc, ! rc_can_use(rc, itype));
test_cleanup();
}
CuSuite *get_race_suite(void)
{
CuSuite *suite = CuSuiteNew();
@ -109,6 +160,7 @@ CuSuite *get_race_suite(void)
SUITE_ADD_TEST(suite, test_rc_defaults);
SUITE_ADD_TEST(suite, test_rc_find);
SUITE_ADD_TEST(suite, test_rc_set_param);
SUITE_ADD_TEST(suite, test_rc_can_use);
return suite;
}

View file

@ -38,6 +38,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "unit.h"
/* util includes */
#include <util/assert.h>
#include <util/attrib.h>
#include <util/bsdstring.h>
#include <util/gamedata.h>
@ -697,6 +698,7 @@ void r_setdemand(region * r, const luxury_type * ltype, int value)
d = *dp;
if (!d) {
d = *dp = malloc(sizeof(struct demand));
assert_alloc(d);
d->next = NULL;
d->type = ltype;
}
@ -768,6 +770,7 @@ region *new_region(int x, int y, struct plane *pl, int uid)
return r;
}
r = calloc(1, sizeof(region));
assert_alloc(r);
r->x = x;
r->y = y;
r->uid = uid;

View file

@ -69,6 +69,7 @@ const resource_type * rtype)
rm->divisor = divisor;
rm->flags = 0;
rm->type = rmt_get(rtype);
assert(rm->type);
update_resource(rm, 1.0);
rm->type->terraform(rm, r);
}
@ -211,3 +212,25 @@ struct rawmaterial_type *rmt_create(struct resource_type *rtype)
rmtype->visible = visible_default;
return rmtype;
}
int(*item_use_fun)(struct unit *u, const struct item_type *itype, int amount,
struct order *ord);
int(*res_limit_fun)(const struct region *, const struct resource_type *);
void(*res_produce_fun)(struct region *, const struct resource_type *, int);
int limit_resource(const struct region *r, const resource_type *rtype)
{
assert(!rtype->raw);
if (res_limit_fun) {
return res_limit_fun(r, rtype);
}
return -1;
}
void produce_resource(struct region *r, const struct resource_type *rtype, int amount)
{
assert(!rtype->raw);
if (res_produce_fun) {
res_produce_fun(r, rtype, amount);
}
}

View file

@ -43,11 +43,6 @@ extern "C" {
struct rawmaterial *next;
} rawmaterial;
typedef int(*rlimit_limit) (const struct region * r,
const struct resource_type * rtype);
typedef void(*rlimit_produce) (struct region * r,
const struct resource_type * rtype, int n);
typedef struct resource_mod {
variant value;
const struct building_type *btype;
@ -55,12 +50,6 @@ extern "C" {
unsigned int flags;
} resource_mod;
typedef struct resource_limit {
rlimit_limit limit;
rlimit_produce produce;
resource_mod *modifiers;
} resource_limit;
typedef struct rawmaterial_type {
const struct resource_type *rtype;
@ -83,6 +72,13 @@ extern "C" {
const struct resource_type *rtype);
struct rawmaterial_type *rmt_create(struct resource_type *rtype);
extern int(*res_limit_fun)(const struct region *, const struct resource_type *);
extern void(*res_produce_fun)(struct region *, const struct resource_type *, int);
extern int (*item_use_fun)(struct unit *, const struct item_type *, int amount,
struct order *ord);
int limit_resource(const struct region *r, const struct resource_type *rtype);
void produce_resource(struct region *r, const struct resource_type *rtype, int amount);
#ifdef __cplusplus
}
#endif

12
src/kernel/rules.c Normal file
View file

@ -0,0 +1,12 @@
#include <platform.h>
#include "rules.h"
int write_rules(const char *filename) {
return -1;
}
int read_rules(const char *filename)
{
return -1;
}

5
src/kernel/rules.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
int read_rules(const char *filename);
int write_rules(const char * filename);

View file

@ -52,6 +52,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <triggers/timeout.h>
/* util includes */
#include <util/assert.h>
#include <util/attrib.h>
#include <util/base36.h>
#include <util/bsdstring.h>
@ -646,6 +647,7 @@ unit *read_unit(struct gamedata *data)
}
else {
u = calloc(sizeof(unit), 1);
assert_alloc(u);
u->no = n;
uhash(u);
}

View file

@ -757,6 +757,28 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
return wtype;
}
static int race_mask = 1;
static void mask_races(xmlNodePtr node, const char *key, int *maskp) {
xmlChar *propValue = xmlGetProp(node, BAD_CAST key);
int mask = 0;
assert(maskp);
if (propValue) {
char * tok = strtok((char *)propValue, " ,");
while (tok) {
race * rc = rc_get_or_create(tok);
if (!rc->mask_item) {
rc->mask_item = race_mask;
race_mask = race_mask << 1;
}
mask |= rc->mask_item;
tok = strtok(NULL, " ,");
}
xmlFree(propValue);
}
*maskp = mask;
}
static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
{
xmlNodePtr node = xpath->node;
@ -767,6 +789,8 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
if (xml_bvalue(node, "cursed", false))
flags |= ITF_CURSED;
if (xml_bvalue(node, "use", false))
flags |= ITF_CANUSE;
if (xml_bvalue(node, "notlost", false))
flags |= ITF_NOTLOST;
if (xml_bvalue(node, "herb", false))
@ -780,6 +804,8 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
itype = rtype->itype ? rtype->itype : it_get_or_create(rtype);
itype->weight = xml_ivalue(node, "weight", 0);
itype->capacity = xml_ivalue(node, "capacity", 0);
mask_races(node, "allow", &itype->mask_allow);
mask_races(node, "deny", &itype->mask_deny);
itype->flags |= flags;
/* reading item/construction */
@ -803,6 +829,10 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
result = xmlXPathEvalExpression(BAD_CAST "potion", xpath);
assert(result->nodesetval->nodeNr <= 1);
if (result->nodesetval->nodeNr != 0) {
if ((itype->flags & ITF_CANUSE) == 0) {
log_error("potion %s has no use attribute", rtype->_name);
itype->flags |= ITF_CANUSE;
}
xpath->node = result->nodesetval->nodeTab[0];
rtype->ptype = xml_readpotion(xpath, itype);
}
@ -843,28 +873,7 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
continue;
}
assert(propValue != NULL);
if (strcmp((const char *)propValue, "give") == 0) {
itype->give =
(int(*)(struct unit *, struct unit *, const struct item_type *, int,
struct order *))fun;
}
else if (strcmp((const char *)propValue, "use") == 0) {
itype->use =
(int(*)(struct unit *, const struct item_type *, int,
struct order *))fun;
}
else if (strcmp((const char *)propValue, "canuse") == 0) {
itype->canuse =
(bool(*)(const struct unit *, const struct item_type *))fun;
}
else if (strcmp((const char *)propValue, "useonother") == 0) {
itype->useonother =
(int(*)(struct unit *, int, const struct item_type *, int,
struct order *))fun;
}
else {
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name);
}
log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, rtype->_name);
xmlFree(propValue);
}
itype->score = xml_ivalue(node, "score", 0);
@ -933,8 +942,6 @@ static int parse_resources(xmlDocPtr doc)
if (xml_bvalue(node, "pooled", true))
flags |= RTF_POOLED;
if (xml_bvalue(node, "limited", false))
flags |= RTF_LIMITED;
name = xmlGetProp(node, BAD_CAST "name");
if (!name) {
@ -965,9 +972,6 @@ static int parse_resources(xmlDocPtr doc)
if (strcmp((const char *)propValue, "change") == 0) {
rtype->uchange = (rtype_uchange)fun;
}
else if (strcmp((const char *)propValue, "get") == 0) {
rtype->uget = (rtype_uget)fun;
}
else if (strcmp((const char *)propValue, "name") == 0) {
rtype->name = (rtype_name)fun;
}
@ -982,100 +986,59 @@ static int parse_resources(xmlDocPtr doc)
rmt_create(rtype);
}
/* reading eressea/resources/resource/resourcelimit */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath);
assert(result->nodesetval->nodeNr <= 1);
if (result->nodesetval->nodeNr != 0) {
resource_limit *rdata = rtype->limit = calloc(1, sizeof(resource_limit));
xmlNodePtr limit = result->nodesetval->nodeTab[0];
if (xml_bvalue(node, "limited", false)) {
rtype->flags |= RTF_LIMITED;
xpath->node = limit;
xmlXPathFreeObject(result);
}
/* reading eressea/resources/resource/modifier */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) {
rtype->modifiers =
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
building_type *btype = NULL;
const race *rc = NULL;
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
if (result->nodesetval != NULL) {
rdata->modifiers =
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
building_type *btype = NULL;
const race *rc = NULL;
propValue = xmlGetProp(node, BAD_CAST "race");
if (propValue != NULL) {
rc = rc_find((const char *)propValue);
if (rc == NULL)
rc = rc_get_or_create((const char *)propValue);
xmlFree(propValue);
}
rdata->modifiers[k].race = rc;
propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) {
btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
rdata->modifiers[k].btype = btype;
propValue = xmlGetProp(node, BAD_CAST "type");
assert(propValue != NULL);
if (strcmp((const char *)propValue, "skill") == 0) {
rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0);
rdata->modifiers[k].flags = RMF_SKILL;
}
else if (strcmp((const char *)propValue, "material") == 0) {
rdata->modifiers[k].value = xml_fraction(node, "value");
rdata->modifiers[k].flags = RMF_SAVEMATERIAL;
}
else if (strcmp((const char *)propValue, "require") == 0) {
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
if (propBldg != NULL) {
btype = bt_get_or_create((const char *)propBldg);
rdata->modifiers[k].btype = btype;
rdata->modifiers[k].flags = RMF_REQUIREDBUILDING;
xmlFree(propBldg);
}
}
else {
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
}
propValue = xmlGetProp(node, BAD_CAST "race");
if (propValue != NULL) {
rc = rc_find((const char *)propValue);
if (rc == NULL)
rc = rc_get_or_create((const char *)propValue);
xmlFree(propValue);
}
}
xmlXPathFreeObject(result);
rtype->modifiers[k].race = rc;
/* reading eressea/resources/resource/resourcelimit/function */
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
if (result->nodesetval != NULL) {
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
pf_generic fun;
propValue = xmlGetProp(node, BAD_CAST "value");
assert(propValue != NULL);
fun = get_function((const char *)propValue);
if (fun == NULL) {
log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name);
xmlFree(propValue);
continue;
}
xmlFree(propValue);
propValue = xmlGetProp(node, BAD_CAST "name");
assert(propValue != NULL);
if (strcmp((const char *)propValue, "produce") == 0) {
rdata->produce = (rlimit_produce)fun;
}
else if (strcmp((const char *)propValue, "limit") == 0) {
rdata->limit = (rlimit_limit)fun;
}
else {
log_error("unknown limit '%s' for resource %s\n", (const char *)propValue, rtype->_name);
}
propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) {
btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
rtype->modifiers[k].btype = btype;
propValue = xmlGetProp(node, BAD_CAST "type");
assert(propValue != NULL);
if (strcmp((const char *)propValue, "skill") == 0) {
rtype->modifiers[k].value.i = xml_ivalue(node, "value", 0);
rtype->modifiers[k].flags = RMF_SKILL;
}
else if (strcmp((const char *)propValue, "material") == 0) {
rtype->modifiers[k].value = xml_fraction(node, "value");
rtype->modifiers[k].flags = RMF_SAVEMATERIAL;
}
else if (strcmp((const char *)propValue, "require") == 0) {
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
if (propBldg != NULL) {
btype = bt_get_or_create((const char *)propBldg);
rtype->modifiers[k].btype = btype;
rtype->modifiers[k].flags = RMF_REQUIREDBUILDING;
xmlFree(propBldg);
}
}
else {
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
}
xmlFree(propValue);
}
}
xmlXPathFreeObject(result);

View file

@ -12,6 +12,9 @@ without prior permission by the authors of Eressea.
#ifndef H_KRNL_XMLREADER_H
#define H_KRNL_XMLREADER_H
struct spell;
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -333,7 +333,7 @@ int peasant_luck_effect(int peasants, int luck, int maxp, double variance)
#endif
static void peasants(region * r)
static void peasants(region * r, int rule)
{
int peasants = rpeasants(r);
int money = rmoney(r);
@ -341,7 +341,7 @@ static void peasants(region * r)
int n, satiated;
int dead = 0;
if (peasants > 0 && config_get_int("rules.peasants.growth", 1)) {
if (peasants > 0 && rule > 0) {
int luck = 0;
double fraction = peasants * peasant_growth_factor();
int births = RAND_ROUND(fraction);
@ -812,6 +812,8 @@ void demographics(void)
static int last_weeks_season = -1;
static int current_season = -1;
int plant_rules = config_get_int("rules.grow.formula", 2);
int horse_rules = config_get_int("rules.horses.growth", 1);
int peasant_rules = config_get_int("rules.peasants.growth", 1);
const struct building_type *bt_harbour = bt_find("harbour");
if (current_season < 0) {
@ -843,7 +845,8 @@ void demographics(void)
* und gewandert sind */
calculate_emigration(r);
peasants(r);
peasants(r, peasant_rules);
if (r->age > 20) {
double mwp = MAX(region_maxworkers(r), 1);
double prob =
@ -854,7 +857,9 @@ void demographics(void)
plagues(r);
}
}
horses(r);
if (horse_rules > 0) {
horses(r);
}
if (plant_rules == 2) { /* E2 */
growing_trees(r, current_season, last_weeks_season);
growing_herbs(r, current_season, last_weeks_season);
@ -3242,11 +3247,6 @@ void update_long_order(unit * u)
static int use_item(unit * u, const item_type * itype, int amount, struct order *ord)
{
int i;
int target = -1;
if (itype->useonother) {
target = read_unitid(u->faction, u->region);
}
i = get_pooled(u, itype->rtype, GET_DEFAULT, amount);
if (amount > i) {
@ -3257,19 +3257,14 @@ static int use_item(unit * u, const item_type * itype, int amount, struct order
return ENOITEM;
}
if (target == -1) {
if (itype->use) {
int result = itype->use(u, itype, amount, ord);
if (result > 0) {
use_pooled(u, itype->rtype, GET_DEFAULT, result);
}
return result;
if (itype->flags & ITF_CANUSE) {
int result = item_use_fun(u, itype, amount, ord);
if (result > 0) {
use_pooled(u, itype->rtype, GET_DEFAULT, result);
}
return EUNUSABLE;
}
else {
return itype->useonother(u, target, itype, amount, ord);
return result;
}
return EUNUSABLE;
}
void monthly_healing(void)
@ -4196,16 +4191,54 @@ void init_processor(void)
}
}
void processorders(void)
static void reset_game(void)
{
region *r;
faction *f;
for (r = regions; r; r = r->next) {
unit *u;
building *b;
r->flags &= RF_SAVEMASK;
for (u = r->units; u; u = u->next) {
u->flags &= UFL_SAVEMASK;
}
for (b = r->buildings; b; b = b->next) {
b->flags &= BLD_SAVEMASK;
}
if (r->land && r->land->ownership && r->land->ownership->owner) {
faction *owner = r->land->ownership->owner;
if (owner == get_monsters()) {
/* some compat-fix, i believe. */
owner = update_owners(r);
}
if (owner) {
fset(r, RF_GUARDED);
}
}
}
for (f = factions; f; f = f->next) {
f->flags &= FFL_SAVEMASK;
}
}
void turn_begin(void)
{
++turn;
reset_game();
}
void turn_process(void)
{
init_processor();
process();
/*************************************************/
if (config_get_int("modules.markets", 0)) {
do_markets();
}
}
void turn_end(void)
{
log_info(" - Attribute altern");
ageing();
remove_empty_units();
@ -4220,6 +4253,13 @@ void processorders(void)
update_spells();
}
void processorders(void)
{
turn_begin();
turn_process();
turn_end();
}
void update_subscriptions(void)
{
FILE *F;

View file

@ -53,8 +53,10 @@ extern "C" {
int enter_building(struct unit *u, struct order *ord, int id, bool report);
int enter_ship(struct unit *u, struct order *ord, int id, bool report);
/* eressea-specific. put somewhere else, please. */
void processorders(void);
void turn_begin(void);
void turn_process(void);
void turn_end(void);
void new_units(void);
void defaultorders(void);

View file

@ -1,6 +1,5 @@
PROJECT(modules C)
SET(_FILES
arena.c
autoseed.c
gmcmd.c
museum.c

View file

@ -1,255 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#include <platform.h>
#include <kernel/config.h>
#if ARENA_MODULE
#include "arena.h"
/* modules include */
#include "score.h"
/* items include */
#include <items/demonseye.h>
/* kernel includes */
#include <kernel/building.h>
#include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/messages.h>
#include <kernel/order.h>
#include <kernel/plane.h>
#include <kernel/pool.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <kernel/terrainid.h>
#include <kernel/unit.h>
#include <move.h>
/* util include */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/event.h>
#include <util/gamedata.h>
#include <util/functions.h>
#include <util/strings.h>
#include <util/lists.h>
#include <util/log.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <storage.h>
/* libc include */
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
/* exports: */
plane *arena = NULL;
/* local vars */
#define CENTRAL_VOLCANO 1
static region *tower_region[6];
static region *start_region[6];
static region *arena_region(int school)
{
return tower_region[school];
}
static building *arena_tower(int school)
{
return arena_region(school)->buildings;
}
static int leave_fail(unit * u)
{
ADDMSG(&u->faction->msgs, msg_message("arena_leave_fail", "unit", u));
return 1;
}
static int
leave_arena(struct unit *u, const struct item_type *itype, int amount,
order * ord)
{
if (!u->building && leave_fail(u)) {
return -1;
}
if (u->building != arena_tower(u->faction->magiegebiet) && leave_fail(u)) {
return -1;
}
UNUSED_ARG(amount);
UNUSED_ARG(ord);
UNUSED_ARG(itype);
assert(!"not implemented");
return 0;
}
static int enter_fail(unit * u)
{
ADDMSG(&u->faction->msgs, msg_message("arena_enter_fail", "region unit",
u->region, u));
return 1;
}
static int
enter_arena(unit * u, const item_type * itype, int amount, order * ord)
{
skill_t sk;
region *r = u->region;
unit *u2;
int fee = 2000;
UNUSED_ARG(ord);
UNUSED_ARG(amount);
UNUSED_ARG(itype);
if (u->faction->score > fee * 5) {
score_t score = u->faction->score / 5;
if (score < INT_MAX) {
fee = (int)score;
}
else {
fee = INT_MAX;
}
}
if (getplane(r) == arena)
return -1;
if (u->number != 1 && enter_fail(u))
return -1;
if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, fee) < fee
&& enter_fail(u))
return -1;
for (sk = 0; sk != MAXSKILLS; ++sk) {
if (get_level(u, sk) > 1 && enter_fail(u))
return -1;
}
for (u2 = r->units; u2; u2 = u2->next)
if (u2->faction == u->faction)
break;
assert(!"not implemented");
/*
for (res=0;res!=MAXRESOURCES;++res) if (res!=R_SILVER && res!=R_ARENA_GATE && (is_item(res) || is_herb(res) || is_potion(res))) {
int x = get_resource(u, res);
if (x) {
if (u2) {
change_resource(u2, res, x);
change_resource(u, res, -x);
}
else if (enter_fail(u)) return -1;
}
}
*/
if (get_money(u) > fee) {
if (u2)
change_money(u2, get_money(u) - fee);
else if (enter_fail(u))
return -1;
}
ADDMSG(&u->faction->msgs, msg_message("arena_enter_fail", "region unit",
u->region, u));
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE, 1);
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, fee);
set_money(u, 109);
fset(u, UFL_ANON_FACTION);
move_unit(u, start_region[rng_int() % 6], NULL);
return 0;
}
#ifdef CENTRAL_VOLCANO
static int caldera_handle(trigger * t, void *data)
{
/* call an event handler on caldera.
* data.v -> ( variant event, int timer )
*/
building *b = (building *)t->data.v;
if (b != NULL) {
unit **up = &b->region->units;
while (*up) {
unit *u = *up;
if (u->building == b) {
message *msg;
if (u->items) {
item **ip = &u->items;
msg = msg_message("caldera_handle_1", "unit items", u, u->items);
while (*ip) {
item *i = *ip;
i_remove(ip, i);
if (*ip == i)
ip = &i->next;
}
}
else {
msg = msg_message("caldera_handle_0", "unit", u);
}
add_message(&u->region->msgs, msg);
set_number(u, 0);
}
if (*up == u)
up = &u->next;
}
}
else {
log_error("could not perform caldera::handle()\n");
}
UNUSED_ARG(data);
return 0;
}
static void caldera_write(const trigger * t, struct storage *store)
{
building *b = (building *)t->data.v;
write_building_reference(b, store);
}
static int caldera_read(trigger * t, struct gamedata *data)
{
int rb =
read_reference(&t->data.v, data, read_building_reference,
resolve_building);
if (rb == 0 && !t->data.v) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
struct trigger_type tt_caldera = {
"caldera",
NULL,
NULL,
caldera_handle,
caldera_write,
caldera_read
};
#endif
void register_arena(void)
{
at_deprecate("hurting", a_readint);
register_function((pf_generic)enter_arena, "enter_arena");
register_function((pf_generic)leave_arena, "leave_arena");
tt_register(&tt_caldera);
}
#endif /* def ARENA_MODULE */

Some files were not shown because too many files have changed in this diff Show more