forked from github/server
Merge pull request #663 from ennorehling/develop
ongoing refactoring towards the noxml branch
This commit is contained in:
commit
2137c51509
73 changed files with 642 additions and 907 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -39,3 +39,6 @@ tmp/
|
||||||
tests/config.lua
|
tests/config.lua
|
||||||
tests/reports/
|
tests/reports/
|
||||||
tests/data/185.dat
|
tests/data/185.dat
|
||||||
|
/quicklist/
|
||||||
|
/cutest/
|
||||||
|
/critbit/
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<resource name="adamantium" limited="yes" material="rm_adamantium">
|
<resource name="adamantium" limited="yes" material="yes">
|
||||||
<item weight="200" score="200">
|
<item weight="200" score="200">
|
||||||
<construction skill="mining" minskill="8"/>
|
<construction skill="mining" minskill="8"/>
|
||||||
</item>
|
</item>
|
||||||
<resourcelimit>
|
<resourcelimit>
|
||||||
<modifier type="require" building="mine"/>
|
<modifier type="require" building="mine"/>
|
||||||
<guard flag="mining"/>
|
|
||||||
</resourcelimit>
|
</resourcelimit>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<building name="castle" capacity="1" fort="yes">
|
<building name="castle" capacity="1" fort="yes">
|
||||||
<function name="name" value="castle_name_2"/>
|
<function name="name" value="castle_name_2"/>
|
||||||
<function name="protection" value="building_protection"/>
|
|
||||||
<function name="taxes" value="lua_building_taxes"/>
|
<function name="taxes" value="lua_building_taxes"/>
|
||||||
<construction skill="building" minskill="1" maxsize="10" defense_bonus="0">
|
<construction skill="building" minskill="1" maxsize="10">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="2" maxsize="40" defense_bonus="1">
|
<construction skill="building" minskill="2" maxsize="40">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="3" maxsize="200" defense_bonus="3">
|
<construction skill="building" minskill="3" maxsize="200">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="4" maxsize="1000" defense_bonus="5">
|
<construction skill="building" minskill="4" maxsize="1000">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="5" maxsize="5000" defense_bonus="8">
|
<construction skill="building" minskill="5" maxsize="5000">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="6" defense_bonus="12">
|
<construction skill="building" minskill="6">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
</building>
|
</building>
|
||||||
|
|
|
@ -1,26 +1,25 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<building name="castle" capacity="1" fort="yes">
|
<building name="castle" capacity="1" fort="yes">
|
||||||
<function name="name" value="castle_name"/>
|
<function name="name" value="castle_name"/>
|
||||||
<function name="protection" value="building_protection"/>
|
<construction skill="building" minskill="1" maxsize="2">
|
||||||
<construction skill="building" minskill="1" maxsize="2" defense_bonus="0">
|
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="1" maxsize="8" defense_bonus="0">
|
<construction skill="building" minskill="1" maxsize="8">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="2" maxsize="40" defense_bonus="1">
|
<construction skill="building" minskill="2" maxsize="40">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="3" maxsize="200" defense_bonus="3">
|
<construction skill="building" minskill="3" maxsize="200">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="4" maxsize="1000" defense_bonus="5">
|
<construction skill="building" minskill="4" maxsize="1000">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="5" maxsize="5000" defense_bonus="8">
|
<construction skill="building" minskill="5" maxsize="5000">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="6" defense_bonus="12">
|
<construction skill="building" minskill="6">
|
||||||
<requirement type="stone" quantity="1"/>
|
<requirement type="stone" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
</building>
|
</building>
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
<building name="illusioncastle" capacity="0" maxcapacity="0" maxsize="0" nobuild="yes"/>
|
<building name="illusioncastle" capacity="0" maxcapacity="0" maxsize="0" nobuild="yes"/>
|
||||||
<building name="xmas_exit" maxsize="10" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes"/>
|
<building name="xmas_exit" maxsize="10" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes"/>
|
||||||
<building name="caldera" capacity="1" nodestroy="yes" nobuild="yes"/>
|
<building name="caldera" capacity="1" nodestroy="yes" nobuild="yes"/>
|
||||||
<building name="genericbuilding" namechange="no" maxsize="1" nobuild="yes"/>
|
<building name="building" namechange="no" maxsize="1" nobuild="yes"/>
|
||||||
<building name="artacademy" maxsize="100" nobuild="yes" nodestroy="yes" unique="yes"/>
|
|
||||||
<building name="artsculpture" namechange="no" maxsize="100" nobuild="yes" nodestroy="yes" unique="yes"/>
|
|
||||||
|
|
||||||
<building name="blessedstonecircle" maxcapacity="3" maxsize="100" nobuild="yes" magic="yes" magres="60" magresbonus="30" auraregen="1.50">
|
<building name="blessedstonecircle" maxcapacity="3" maxsize="100" nobuild="yes" magic="yes" magres="60" magresbonus="30" auraregen="1.50">
|
||||||
<construction skill="building" minskill="2" reqsize="100" maxsize="100">
|
<construction skill="building" minskill="2" reqsize="100" maxsize="100">
|
||||||
|
|
|
@ -912,17 +912,9 @@
|
||||||
<string name="illusioncastle">
|
<string name="illusioncastle">
|
||||||
<text locale="de">Traumschlößchen</text>
|
<text locale="de">Traumschlößchen</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="genericbuilding">
|
<string name="building">
|
||||||
<text locale="de">Struktur</text>
|
<text locale="de">Struktur</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="artacademy">
|
|
||||||
<text locale="de">Akademie der Künste</text>
|
|
||||||
<text locale="en">academy of arts</text>
|
|
||||||
</string>
|
|
||||||
<string name="artsculpture">
|
|
||||||
<text locale="de">Skulptur</text>
|
|
||||||
<text locale="en">sculpture</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<!--Testitem -->
|
<!--Testitem -->
|
||||||
<string name="wand">
|
<string name="wand">
|
||||||
|
@ -6619,53 +6611,17 @@
|
||||||
<text locale="de">EINLADEN</text>
|
<text locale="de">EINLADEN</text>
|
||||||
<text locale="en">INVITE</text>
|
<text locale="en">INVITE</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="rm_stone">
|
|
||||||
<text locale="de">Steine</text>
|
|
||||||
<text locale="en">stones</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="rm_horse">
|
<string name="sapling">
|
||||||
<text locale="de">Pferde</text>
|
|
||||||
<text locale="en">horses</text>
|
|
||||||
</string>
|
|
||||||
<string name="rm_peasant">
|
|
||||||
<text locale="de">Bauern</text>
|
|
||||||
<text locale="en">peasants</text>
|
|
||||||
</string>
|
|
||||||
<string name="rm_money">
|
|
||||||
<text locale="de">Silber</text>
|
|
||||||
<text locale="en">silver</text>
|
|
||||||
</string>
|
|
||||||
<string name="rm_laen">
|
|
||||||
<text locale="de">Laen</text>
|
|
||||||
<text locale="en">laen</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="rm_sapling">
|
|
||||||
<text locale="de">Schößlinge</text>
|
<text locale="de">Schößlinge</text>
|
||||||
<text locale="en">saplings</text>
|
<text locale="en">saplings</text>
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="rm_mallornsapling">
|
<string name="mallornsapling">
|
||||||
<text locale="de">Mallornschößlinge</text>
|
<text locale="de">Mallornschößlinge</text>
|
||||||
<text locale="en">mallorn saplings</text>
|
<text locale="en">mallorn saplings</text>
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="rm_tree">
|
|
||||||
<text locale="de">Bäume</text>
|
|
||||||
<text locale="en">trees</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="rm_mallorn">
|
|
||||||
<text locale="de">Mallorn</text>
|
|
||||||
<text locale="en">mallorn</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="rm_iron">
|
|
||||||
<text locale="de">Eisen</text>
|
|
||||||
<text locale="en">iron</text>
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="Winter">
|
<string name="Winter">
|
||||||
<text locale="de">Winter</text>
|
<text locale="de">Winter</text>
|
||||||
<text locale="en">winter</text>
|
<text locale="en">winter</text>
|
||||||
|
|
|
@ -310,7 +310,7 @@
|
||||||
<string name="dam">
|
<string name="dam">
|
||||||
<text locale="en">dam</text>
|
<text locale="en">dam</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="genericbuilding">
|
<string name="building">
|
||||||
<text locale="en">structure</text>
|
<text locale="en">structure</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="harbour">
|
<string name="harbour">
|
||||||
|
|
|
@ -324,7 +324,7 @@
|
||||||
<string name="dam">
|
<string name="dam">
|
||||||
<text locale="fr">barrage</text>
|
<text locale="fr">barrage</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="genericbuilding">
|
<string name="building">
|
||||||
<text locale="fr">bâtiment</text>
|
<text locale="fr">bâtiment</text>
|
||||||
</string>
|
</string>
|
||||||
<string name="harbour">
|
<string name="harbour">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="horse" limited="yes" material="rm_horse">
|
<resource name="horse" limited="yes">
|
||||||
<item big="yes" weight="5000" score="10" capacity="7000" animal="yes">
|
<item big="yes" weight="5000" score="10" capacity="7000" animal="yes">
|
||||||
<construction skill="training" minskill="1"/>
|
<construction skill="training" minskill="1"/>
|
||||||
<function name="give" value="givehorses"/>
|
<function name="give" value="givehorses"/>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="iron" limited="yes" material="rm_iron">
|
<resource name="iron" limited="yes" material="yes">
|
||||||
<item weight="500" score="10">
|
<item weight="500" score="10">
|
||||||
<construction skill="mining" minskill="1"/>
|
<construction skill="mining" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="laen" limited="yes" material="rm_laen">
|
<resource name="laen" limited="yes" material="yes">
|
||||||
<item weight="200" score="100">
|
<item weight="200" score="100">
|
||||||
<construction skill="mining" minskill="7"/>
|
<construction skill="mining" minskill="7"/>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="log" material="rm_tree">
|
<resource name="log">
|
||||||
<item weight="500" score="10">
|
<item weight="500" score="10">
|
||||||
<construction skill="forestry" minskill="1"/>
|
<construction skill="forestry" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="mallorn" material="rm_mallorn">
|
<resource name="mallorn">
|
||||||
<item weight="500" score="30">
|
<item weight="500" score="30">
|
||||||
<construction skill="forestry" minskill="2"/>
|
<construction skill="forestry" minskill="2"/>
|
||||||
</item>
|
</item>
|
||||||
<resourcelimit>
|
<resourcelimit>
|
||||||
<modifier building="sawmill" type="skill" value="1"/>
|
<modifier building="sawmill" type="skill" value="1"/>
|
||||||
<modifier building="sawmill" type="material" value="0.5"/>
|
<modifier building="sawmill" type="material" value="0.5"/>
|
||||||
<guard flag="logging"/>
|
|
||||||
<function name="produce" value="lua_produceresource"/>
|
<function name="produce" value="lua_produceresource"/>
|
||||||
<function name="limit" value="lua_limitresource"/>
|
<function name="limit" value="lua_limitresource"/>
|
||||||
</resourcelimit>
|
</resourcelimit>
|
||||||
|
|
|
@ -3,4 +3,8 @@
|
||||||
<item weight="10" score="100">
|
<item weight="10" score="100">
|
||||||
<construction skill="herbalism" minskill="4"/>
|
<construction skill="herbalism" minskill="4"/>
|
||||||
</item>
|
</item>
|
||||||
|
<resourcelimit>
|
||||||
|
<function name="produce" value="lua_produceresource"/>
|
||||||
|
<function name="limit" value="lua_limitresource"/>
|
||||||
|
</resourcelimit>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -3,4 +3,8 @@
|
||||||
<item weight="10" score="50">
|
<item weight="10" score="50">
|
||||||
<construction skill="herbalism" minskill="3"/>
|
<construction skill="herbalism" minskill="3"/>
|
||||||
</item>
|
</item>
|
||||||
|
<resourcelimit>
|
||||||
|
<function name="produce" value="lua_produceresource"/>
|
||||||
|
<function name="limit" value="lua_limitresource"/>
|
||||||
|
</resourcelimit>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="stone" limited="yes" material="rm_stone">
|
<resource name="stone" limited="yes" material="yes">
|
||||||
<item weight="6000" score="10" big="yes">
|
<item weight="6000" score="10" big="yes">
|
||||||
<construction skill="quarrying" minskill="1"/>
|
<construction skill="quarrying" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -5,15 +5,14 @@
|
||||||
|
|
||||||
<building name="watch" maxsize="10" capacity="1" fort="yes">
|
<building name="watch" maxsize="10" capacity="1" fort="yes">
|
||||||
<function name="name" value="fort_name"/>
|
<function name="name" value="fort_name"/>
|
||||||
<function name="protection" value="building_protection"/>
|
|
||||||
<function name="taxes" value="lua_building_taxes"/>
|
<function name="taxes" value="lua_building_taxes"/>
|
||||||
<construction skill="building" minskill="1" maxsize="5" defense_bonus="0">
|
<construction skill="building" minskill="1" maxsize="5">
|
||||||
<requirement type="log" quantity="1"/>
|
<requirement type="log" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="2" maxsize="5" defense_bonus="1">
|
<construction skill="building" minskill="2" maxsize="5">
|
||||||
<requirement type="log" quantity="1"/>
|
<requirement type="log" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
<construction skill="building" minskill="2" defense_bonus="2">
|
<construction skill="building" minskill="2">
|
||||||
<requirement type="log" quantity="1"/>
|
<requirement type="log" quantity="1"/>
|
||||||
</construction>
|
</construction>
|
||||||
</building>
|
</building>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="iron" limited="yes" material="rm_iron">
|
<resource name="iron" limited="yes" material="yes">
|
||||||
<item weight="500" score="10">
|
<item weight="500" score="10">
|
||||||
<construction skill="mining" minskill="1"/>
|
<construction skill="mining" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
<resourcelimit>
|
<resourcelimit>
|
||||||
<modifier building="mine" type="skill" value="1"/>
|
<modifier building="mine" type="skill" value="1"/>
|
||||||
<modifier building="mine" type="material" value="0.5"/>
|
<modifier building="mine" type="material" value="0.5"/>
|
||||||
<guard flag="mining"/>
|
|
||||||
</resourcelimit>
|
</resourcelimit>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="mallornseed" limited="yes">
|
<resource name="mallornseed">
|
||||||
<item weight="10" score="100"/>
|
<item weight="10" score="100"/>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="seed" limited="yes">
|
<resource name="seed">
|
||||||
<item weight="10" score="50"/>
|
<item weight="10" score="50"/>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resource name="stone" limited="yes" material="rm_stone">
|
<resource name="stone" limited="yes" material="yes">
|
||||||
<item weight="6000" score="10" big="yes">
|
<item weight="6000" score="10" big="yes">
|
||||||
<construction skill="quarrying" minskill="1"/>
|
<construction skill="quarrying" minskill="1"/>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1,20 +1,6 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<resource name="instantartsculpture">
|
|
||||||
<function name="change" value="changeitem"/>
|
|
||||||
<item weight="0">
|
|
||||||
<function name="use" value="use_instantartsculpture"/>
|
|
||||||
</item>
|
|
||||||
</resource>
|
|
||||||
|
|
||||||
<resource name="instantartacademy">
|
|
||||||
<function name="change" value="changeitem"/>
|
|
||||||
<item weight="0">
|
|
||||||
<function name="use" value="use_instantartacademy"/>
|
|
||||||
</item>
|
|
||||||
</resource>
|
|
||||||
|
|
||||||
<resource name="aurapotion50">
|
<resource name="aurapotion50">
|
||||||
<function name="change" value="changeitem"/>
|
<function name="change" value="changeitem"/>
|
||||||
<item weight="0">
|
<item weight="0">
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
<building name="temple" maxsize="50" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" auraregen="1.00" />
|
<building name="temple" maxsize="50" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" auraregen="1.00" />
|
||||||
<building name="portal" maxsize="2" capacity="1" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" />
|
<building name="portal" maxsize="2" capacity="1" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" />
|
||||||
<building name="pavilion" maxsize="2" capacity="1" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" />
|
<building name="pavilion" maxsize="2" capacity="1" maxcapacity="2" nobuild="yes" nodestroy="yes" unique="yes" />
|
||||||
|
<building name="artacademy" maxsize="100" nobuild="yes" nodestroy="yes" unique="yes"/>
|
||||||
</buildings>
|
</buildings>
|
||||||
|
|
|
@ -63,19 +63,6 @@
|
||||||
</item>
|
</item>
|
||||||
</resource>
|
</resource>
|
||||||
|
|
||||||
<!-- art rewards -->
|
|
||||||
<resource name="trappedairelemental">
|
|
||||||
<item weight="0">
|
|
||||||
<function name="use" value="use_trappedairelemental"/>
|
|
||||||
</item>
|
|
||||||
</resource>
|
|
||||||
|
|
||||||
<resource name="hornofdancing">
|
|
||||||
<item weight="0">
|
|
||||||
<function name="use" value="use_hornofdancing"/>
|
|
||||||
</item>
|
|
||||||
</resource>
|
|
||||||
|
|
||||||
<!-- museum items -->
|
<!-- museum items -->
|
||||||
<resource name="questkey1" appearance="key">
|
<resource name="questkey1" appearance="key">
|
||||||
<!-- Key for an old quest. placeholder item -->
|
<!-- Key for an old quest. placeholder item -->
|
||||||
|
|
|
@ -352,37 +352,9 @@
|
||||||
<!-- ending here: Wildente and Jadee's wedding -->
|
<!-- ending here: Wildente and Jadee's wedding -->
|
||||||
|
|
||||||
<!-- art rewards begin -->
|
<!-- art rewards begin -->
|
||||||
<string name="hornofdancing">
|
<string name="artacademy">
|
||||||
<text locale="de">Horn des Tanzes</text>
|
<text locale="de">Akademie der Künste</text>
|
||||||
<text locale="en">horn of dancing</text>
|
<text locale="en">academy of arts</text>
|
||||||
</string>
|
|
||||||
<string name="hornofdancing_p">
|
|
||||||
<text locale="de">Hörner des Tanzes</text>
|
|
||||||
<text locale="en">horns of dancing</text>
|
|
||||||
</string>
|
|
||||||
<string name="instantartacademy">
|
|
||||||
<text locale="de">Miniatur einer Akademie der Künste</text>
|
|
||||||
<text locale="en">academy of arts in a box</text>
|
|
||||||
</string>
|
|
||||||
<string name="instantartacademy_p">
|
|
||||||
<text locale="de">Miniaturen einer Akademie der Künste</text>
|
|
||||||
<text locale="en">academies of arts in a box</text>
|
|
||||||
</string>
|
|
||||||
<string name="instantartsculpture">
|
|
||||||
<text locale="de">Miniatur einer Skulptur</text>
|
|
||||||
<text locale="en">art sculpture in a box</text>
|
|
||||||
</string>
|
|
||||||
<string name="instantartsculpture_p">
|
|
||||||
<text locale="de">Miniaturen einer Skulptur</text>
|
|
||||||
<text locale="en">art sculptures in a box</text>
|
|
||||||
</string>
|
|
||||||
<string name="trappedairelemental">
|
|
||||||
<text locale="de">Gefangener Windgeist</text>
|
|
||||||
<text locale="en">trapped air elemental</text>
|
|
||||||
</string>
|
|
||||||
<string name="trappedairelemental_p">
|
|
||||||
<text locale="de">Gefangene Windgeister</text>
|
|
||||||
<text locale="en">trapped air elementals</text>
|
|
||||||
</string>
|
</string>
|
||||||
<string name="aurapotion50">
|
<string name="aurapotion50">
|
||||||
<text locale="de">Auratrank</text>
|
<text locale="de">Auratrank</text>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<items>
|
|
||||||
</items>
|
|
|
@ -38,8 +38,47 @@ function hp_changeresource(u, delta)
|
||||||
return hp
|
return hp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function mallorn_region(r)
|
||||||
|
return r:get_flag(1) -- RF_MALLORN
|
||||||
|
end
|
||||||
|
|
||||||
|
function seed_limit(r)
|
||||||
|
if mallorn_region(r) then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return r:get_resource("seed")
|
||||||
|
end
|
||||||
|
|
||||||
|
function seed_produce(r, n)
|
||||||
|
if not mallorn_region(r) then
|
||||||
|
local seeds = r:get_resource("seed")
|
||||||
|
if seeds>=n then
|
||||||
|
r:set_resource("seed", seeds-n)
|
||||||
|
else
|
||||||
|
r:set_resource("seed", 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mallornseed_limit(r)
|
||||||
|
if mallorn_region(r) then
|
||||||
|
return r:get_resource("seed")
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function mallornseed_produce(r, n)
|
||||||
|
if mallorn_region(r) then
|
||||||
|
local seeds = r:get_resource("seed")
|
||||||
|
if seeds>=n then
|
||||||
|
r:set_resource("seed", seeds-n)
|
||||||
|
else
|
||||||
|
r:set_resource("seed", 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
function horse_limit(r)
|
function horse_limit(r)
|
||||||
return r:get_resource("horse")
|
return r:get_resource("horse")
|
||||||
end
|
end
|
||||||
|
|
||||||
function horse_produce(r, n)
|
function horse_produce(r, n)
|
||||||
|
@ -52,9 +91,6 @@ function horse_produce(r, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
function log_limit(r)
|
function log_limit(r)
|
||||||
-- if r:get_flag(1) then -- RF_MALLORN
|
|
||||||
-- return 0
|
|
||||||
-- end
|
|
||||||
return r:get_resource("tree") + r:get_resource("sapling")
|
return r:get_resource("tree") + r:get_resource("sapling")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,7 +111,7 @@ function log_produce(r, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mallorn_limit(r)
|
function mallorn_limit(r)
|
||||||
if not r:get_flag(1) then -- RF_MALLORN
|
if not mallorn_region(r) then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
return r:get_resource("tree") + r:get_resource("sapling")
|
return r:get_resource("tree") + r:get_resource("sapling")
|
||||||
|
|
|
@ -438,10 +438,9 @@ function test_recruit()
|
||||||
u:add_item("money", 110*n+20)
|
u:add_item("money", 110*n+20)
|
||||||
u:add_order("REKRUTIERE " .. n)
|
u:add_order("REKRUTIERE " .. n)
|
||||||
process_orders()
|
process_orders()
|
||||||
assert(u.number == n+1)
|
assert_equal(n+1, u.number)
|
||||||
local p = r:get_resource("peasant")
|
local p = r:get_resource("peasant")
|
||||||
assert(p<200 and p>=200-n)
|
assert_true(p<200 and p>=200-n)
|
||||||
-- assert(u:get_item("money")==10)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_produce()
|
function test_produce()
|
||||||
|
@ -468,7 +467,7 @@ function test_work()
|
||||||
u:clear_orders()
|
u:clear_orders()
|
||||||
u:add_order("ARBEITEN")
|
u:add_order("ARBEITEN")
|
||||||
process_orders()
|
process_orders()
|
||||||
assert(u:get_item("money")>=10)
|
assert_equal(20, u:get_item("money"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_upkeep()
|
function test_upkeep()
|
||||||
|
@ -480,7 +479,7 @@ function test_upkeep()
|
||||||
u:clear_orders()
|
u:clear_orders()
|
||||||
u:add_order("LERNE Waffenbau")
|
u:add_order("LERNE Waffenbau")
|
||||||
process_orders()
|
process_orders()
|
||||||
assert(u:get_item("money")==u.number)
|
assert_equal(u:get_item("money"), u.number)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_id()
|
function test_id()
|
||||||
|
@ -488,50 +487,39 @@ function test_id()
|
||||||
|
|
||||||
local f = faction.create("noreply11@eressea.de", "human", "de")
|
local f = faction.create("noreply11@eressea.de", "human", "de")
|
||||||
f.id = atoi36("42")
|
f.id = atoi36("42")
|
||||||
assert(get_faction(42)~=f)
|
assert_not_equal(f, get_faction(42))
|
||||||
assert(get_faction("42")==f)
|
assert_equal(f, get_faction("42"))
|
||||||
assert(get_faction(atoi36("42"))==f)
|
assert_equal(f, get_faction(atoi36("42")))
|
||||||
|
|
||||||
local u = unit.create(f, r, 1)
|
local u = unit.create(f, r, 1)
|
||||||
u.id = atoi36("42")
|
u.id = atoi36("42")
|
||||||
assert(get_unit(42)~=u)
|
assert_not_equal(get_unit(42), u)
|
||||||
assert(get_unit("42")==u)
|
assert_equal(get_unit("42"), u)
|
||||||
assert(get_unit(atoi36("42"))==u)
|
assert_equal(get_unit(atoi36("42")), u)
|
||||||
|
|
||||||
local b = building.create(r, "castle")
|
local b = building.create(r, "castle")
|
||||||
-- <not working> b.id = atoi36("42")
|
-- <not working> b.id = atoi36("42")
|
||||||
local fortytwo = itoa36(b.id)
|
local fortytwo = itoa36(b.id)
|
||||||
assert(get_building(fortytwo)==b)
|
assert_equal(get_building(fortytwo), b)
|
||||||
assert(get_building(atoi36(fortytwo))==b)
|
assert_equal(get_building(atoi36(fortytwo)), b)
|
||||||
|
|
||||||
local s = _test_create_ship(r)
|
local s = _test_create_ship(r)
|
||||||
assert_not_nil(s)
|
assert_not_nil(s)
|
||||||
-- <not working> s.id = atoi36("42")
|
-- <not working> s.id = atoi36("42")
|
||||||
local fortytwo = itoa36(s.id)
|
local fortytwo = itoa36(s.id)
|
||||||
assert(get_ship(fortytwo)==s)
|
assert_equal(get_ship(fortytwo), s)
|
||||||
assert(get_ship(atoi36(fortytwo))==s)
|
assert_equal(get_ship(atoi36(fortytwo)), s)
|
||||||
end
|
|
||||||
|
|
||||||
function test_herbalism()
|
|
||||||
local r = region.create(0, 0, "plain")
|
|
||||||
local f = faction.create("noreply12@eressea.de", "human", "de")
|
|
||||||
local u = unit.create(f, r, 1)
|
|
||||||
u:add_item("money", u.number * 100)
|
|
||||||
u:set_skill("herbalism", 5)
|
|
||||||
u:clear_orders()
|
|
||||||
u:add_order("MACHE Samen")
|
|
||||||
process_orders()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_mallorn()
|
function test_mallorn()
|
||||||
local r = region.create(0, 0, "plain")
|
local r = region.create(0, 0, "plain")
|
||||||
r:set_flag(1, false) -- not mallorn
|
r:set_flag(1, false) -- not mallorn
|
||||||
r:set_resource("tree", 100)
|
r:set_resource("tree", 100)
|
||||||
assert(r:get_resource("tree")==100)
|
assert_equal(100, r:get_resource("tree"))
|
||||||
local m = region.create(0, 0, "plain")
|
local m = region.create(0, 0, "plain")
|
||||||
m:set_flag(1, true) -- mallorn
|
m:set_flag(1, true) -- mallorn
|
||||||
m:set_resource("tree", 100)
|
m:set_resource("tree", 100)
|
||||||
assert(m:get_resource("tree")==100)
|
assert_equal(100, m:get_resource("tree"))
|
||||||
|
|
||||||
local f = faction.create("noreply13@eressea.de", "human", "de")
|
local f = faction.create("noreply13@eressea.de", "human", "de")
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,38 @@ require "lunit"
|
||||||
|
|
||||||
module("tests.e2.e2features", package.seeall, lunit.testcase )
|
module("tests.e2.e2features", 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")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_herbalism()
|
||||||
|
-- OBS: herbalism is currently an E2-only skill
|
||||||
|
local r = region.create(0, 0, "plain")
|
||||||
|
local f = faction.create("herbalism@eressea.de", "human", "de")
|
||||||
|
local u = unit.create(f, r, 1)
|
||||||
|
|
||||||
|
eressea.settings.set("rules.grow.formula", 0) -- plants do not grow
|
||||||
|
u:add_item("money", u.number * 100)
|
||||||
|
u:set_skill("herbalism", 5)
|
||||||
|
r:set_resource("seed", 100)
|
||||||
|
r:set_flag(1, false) -- regular trees
|
||||||
|
u:clear_orders()
|
||||||
|
u:add_order("MACHE Samen")
|
||||||
|
process_orders()
|
||||||
|
assert_equal(1, u:get_item("seed"))
|
||||||
|
assert_equal(99, r:get_resource("seed"))
|
||||||
|
r:set_flag(1, true) -- mallorn
|
||||||
|
u:clear_orders()
|
||||||
|
u:add_order("MACHE Mallornsamen")
|
||||||
|
process_orders()
|
||||||
|
assert_equal(1, u:get_item("mallornseed"))
|
||||||
|
assert_equal(98, r:get_resource("seed"))
|
||||||
|
end
|
||||||
|
|
||||||
function test_build_harbour()
|
function test_build_harbour()
|
||||||
-- try to reproduce mantis bug 2221
|
-- try to reproduce mantis bug 2221
|
||||||
local r = region.create(0, 0, "plain")
|
local r = region.create(0, 0, "plain")
|
||||||
|
@ -42,13 +74,6 @@ local function two_units(r, f1, f2)
|
||||||
return one_unit(r, f1), one_unit(r, f2)
|
return one_unit(r, f1), one_unit(r, f2)
|
||||||
end
|
end
|
||||||
|
|
||||||
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")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_learn()
|
function test_learn()
|
||||||
eressea.settings.set("study.random_progress", "0")
|
eressea.settings.set("study.random_progress", "0")
|
||||||
local r = region.create(0, 0, "plain")
|
local r = region.create(0, 0, "plain")
|
||||||
|
|
54
src/battle.c
54
src/battle.c
|
@ -1059,7 +1059,7 @@ static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_
|
||||||
return modifier;
|
return modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awtype, double *magres) {
|
int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awtype, variant *magres) {
|
||||||
fighter *df = dt.fighter;
|
fighter *df = dt.fighter;
|
||||||
unit *du = df->unit;
|
unit *du = df->unit;
|
||||||
int ar = 0, an, am;
|
int ar = 0, an, am;
|
||||||
|
@ -1110,21 +1110,31 @@ int calculate_armor(troop dt, const weapon_type *dwtype, const weapon_type *awty
|
||||||
|
|
||||||
if (magres) {
|
if (magres) {
|
||||||
/* calculate damage multiplier for magical damage */
|
/* calculate damage multiplier for magical damage */
|
||||||
double res = 1.0 - magic_resistance(du);
|
variant res;
|
||||||
|
|
||||||
|
res = frac_sub(frac_one, magic_resistance(du));
|
||||||
|
|
||||||
if (u_race(du)->battle_flags & BF_EQUIPMENT) {
|
if (u_race(du)->battle_flags & BF_EQUIPMENT) {
|
||||||
/* der Effekt von Laen steigt nicht linear */
|
/* der Effekt von Laen steigt nicht linear */
|
||||||
if (armor && fval(armor, ATF_LAEN))
|
if (armor && fval(armor, ATF_LAEN)) {
|
||||||
res *= (1 - armor->magres);
|
res = frac_mul(res, frac_sub(frac_one, armor->magres));
|
||||||
if (shield && fval(shield, ATF_LAEN))
|
}
|
||||||
res *= (1 - shield->magres);
|
if (shield && fval(shield, ATF_LAEN)) {
|
||||||
if (dwtype)
|
res = frac_mul(res, frac_sub(frac_one, shield->magres));
|
||||||
res *= (1 - dwtype->magres);
|
}
|
||||||
|
if (dwtype) {
|
||||||
|
res = frac_mul(res, frac_sub(frac_one, dwtype->magres));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gegen Magie wirkt nur nat<61>rliche und magische R<>stung */
|
/* gegen Magie wirkt nur natuerliche und magische Ruestung */
|
||||||
ar = an + am;
|
ar = an + am;
|
||||||
*magres = res > 0 ? res : 0;
|
if (res.sa[0] >= 0) {
|
||||||
|
*magres = res;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*magres = frac_make(0, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ar;
|
return ar;
|
||||||
|
@ -1147,7 +1157,7 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
|
||||||
const weapon_type *dwtype = NULL;
|
const weapon_type *dwtype = NULL;
|
||||||
const weapon_type *awtype = NULL;
|
const weapon_type *awtype = NULL;
|
||||||
const weapon *weapon;
|
const weapon *weapon;
|
||||||
double res = 1.0;
|
variant res = frac_make(1, 1);
|
||||||
|
|
||||||
int rda, sk = 0, sd;
|
int rda, sk = 0, sd;
|
||||||
bool magic = false;
|
bool magic = false;
|
||||||
|
@ -1190,9 +1200,9 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO not sure if res could be > 1 here */
|
|
||||||
if (magic) {
|
if (magic) {
|
||||||
da = (int)(MAX(da * res, 0));
|
res = frac_mul(frac_make(da, 1), res);
|
||||||
|
da = res.sa[0] / res.sa[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != AT_COMBATSPELL && type != AT_SPELL) {
|
if (type != AT_COMBATSPELL && type != AT_SPELL) {
|
||||||
|
@ -1892,10 +1902,11 @@ int skilldiff(troop at, troop dt, int dist)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (df->building) {
|
if (df->building) {
|
||||||
if (df->building->attribs) {
|
building *b = df->building;
|
||||||
|
if (b->attribs) {
|
||||||
const curse_type *strongwall_ct = ct_find("strongwall");
|
const curse_type *strongwall_ct = ct_find("strongwall");
|
||||||
if (strongwall_ct) {
|
if (strongwall_ct) {
|
||||||
curse *c = get_curse(df->building->attribs, strongwall_ct);
|
curse *c = get_curse(b->attribs, strongwall_ct);
|
||||||
if (curse_active(c)) {
|
if (curse_active(c)) {
|
||||||
/* wirkt auf alle Geb<65>ude */
|
/* wirkt auf alle Geb<65>ude */
|
||||||
skdiff -= curse_geteffect_int(c);
|
skdiff -= curse_geteffect_int(c);
|
||||||
|
@ -1903,15 +1914,16 @@ int skilldiff(troop at, troop dt, int dist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (df->building->type->protection) {
|
if (b->type->flags & BTF_FORTIFICATION) {
|
||||||
int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS);
|
int stage = buildingeffsize(b, false);
|
||||||
if (beff) {
|
int beff = building_protection(b->type, stage);
|
||||||
|
if (beff > 0) {
|
||||||
skdiff -= beff;
|
skdiff -= beff;
|
||||||
is_protected = 2;
|
is_protected = 2;
|
||||||
if (df->building->attribs) {
|
if (b->attribs) {
|
||||||
const curse_type *magicwalls_ct = ct_find("magicwalls");
|
const curse_type *magicwalls_ct = ct_find("magicwalls");
|
||||||
if (magicwalls_ct
|
if (magicwalls_ct
|
||||||
&& curse_active(get_curse(df->building->attribs, magicwalls_ct))) {
|
&& curse_active(get_curse(b->attribs, magicwalls_ct))) {
|
||||||
/* Verdoppelt Burgenbonus */
|
/* Verdoppelt Burgenbonus */
|
||||||
skdiff -= beff;
|
skdiff -= beff;
|
||||||
}
|
}
|
||||||
|
@ -2022,7 +2034,7 @@ void damage_building(battle * b, building * bldg, int damage_abs)
|
||||||
|
|
||||||
/* Wenn Burg, dann gucken, ob die Leute alle noch in das Geb<65>ude passen. */
|
/* Wenn Burg, dann gucken, ob die Leute alle noch in das Geb<65>ude passen. */
|
||||||
|
|
||||||
if (bldg->type->protection) {
|
if (bldg->type->flags & BTF_FORTIFICATION) {
|
||||||
side *s;
|
side *s;
|
||||||
|
|
||||||
bldg->sizeleft = bldg->size;
|
bldg->sizeleft = bldg->size;
|
||||||
|
|
|
@ -248,7 +248,7 @@ extern "C" {
|
||||||
int count_enemies(struct battle *b, const struct fighter *af,
|
int count_enemies(struct battle *b, const struct fighter *af,
|
||||||
int minrow, int maxrow, int select);
|
int minrow, int maxrow, int select);
|
||||||
int natural_armor(struct unit * u);
|
int natural_armor(struct unit * u);
|
||||||
int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, double *magres);
|
int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, union variant *magres);
|
||||||
bool terminate(troop dt, troop at, int type, const char *damage,
|
bool terminate(troop dt, troop at, int type, const char *damage,
|
||||||
bool missile);
|
bool missile);
|
||||||
extern void message_all(battle * b, struct message *m);
|
extern void message_all(battle * b, struct message *m);
|
||||||
|
|
|
@ -26,7 +26,7 @@ static void test_make_fighter(CuTest * tc)
|
||||||
faction * f;
|
faction * f;
|
||||||
const resource_type *rtype;
|
const resource_type *rtype;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
test_create_horse();
|
test_create_horse();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
f = test_create_faction(NULL);
|
f = test_create_faction(NULL);
|
||||||
|
@ -60,8 +60,17 @@ static void test_make_fighter(CuTest * tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_two(const building * b, const unit * u, building_bonus bonus) {
|
static building_type * setup_castle(void) {
|
||||||
return 2;
|
building_type * btype;
|
||||||
|
construction *cons;
|
||||||
|
|
||||||
|
btype = bt_get_or_create("castle");
|
||||||
|
btype->flags |= BTF_FORTIFICATION;
|
||||||
|
cons = btype->construction = calloc(1, sizeof(construction));
|
||||||
|
cons->maxsize = 5;
|
||||||
|
cons = cons->improvement = calloc(1, sizeof(construction));
|
||||||
|
cons->maxsize = -1;
|
||||||
|
return btype;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_defenders_get_building_bonus(CuTest * tc)
|
static void test_defenders_get_building_bonus(CuTest * tc)
|
||||||
|
@ -72,16 +81,13 @@ static void test_defenders_get_building_bonus(CuTest * tc)
|
||||||
fighter *df, *af;
|
fighter *df, *af;
|
||||||
battle *b;
|
battle *b;
|
||||||
side *ds, *as;
|
side *ds, *as;
|
||||||
int diff;
|
|
||||||
troop dt, at;
|
troop dt, at;
|
||||||
building_type * btype;
|
building_type * btype;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
|
btype = setup_castle();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
btype = bt_get_or_create("castle");
|
|
||||||
btype->protection = &add_two;
|
|
||||||
bld = test_create_building(r, btype);
|
bld = test_create_building(r, btype);
|
||||||
bld->size = 10;
|
|
||||||
|
|
||||||
du = test_create_unit(test_create_faction(NULL), r);
|
du = test_create_unit(test_create_faction(NULL), r);
|
||||||
au = test_create_unit(test_create_faction(NULL), r);
|
au = test_create_unit(test_create_faction(NULL), r);
|
||||||
|
@ -101,11 +107,14 @@ static void test_defenders_get_building_bonus(CuTest * tc)
|
||||||
at.fighter = af;
|
at.fighter = af;
|
||||||
at.index = 0;
|
at.index = 0;
|
||||||
|
|
||||||
diff = skilldiff(at, dt, 0);
|
bld->size = 10; /* stage 1 building */
|
||||||
CuAssertIntEquals(tc, -2, diff);
|
CuAssertIntEquals(tc, -1, skilldiff(at, dt, 0));
|
||||||
|
CuAssertIntEquals(tc, 0, skilldiff(dt, at, 0));
|
||||||
|
|
||||||
|
bld->size = 1; /* stage 0 building */
|
||||||
|
CuAssertIntEquals(tc, 0, skilldiff(at, dt, 0));
|
||||||
|
CuAssertIntEquals(tc, 0, skilldiff(dt, at, 0));
|
||||||
|
|
||||||
diff = skilldiff(dt, at, 0);
|
|
||||||
CuAssertIntEquals(tc, 0, diff);
|
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
@ -120,10 +129,10 @@ static void test_attackers_get_no_building_bonus(CuTest * tc)
|
||||||
side *as;
|
side *as;
|
||||||
building_type * btype;
|
building_type * btype;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
btype = bt_get_or_create("castle");
|
btype = setup_castle();
|
||||||
btype->protection = &add_two;
|
btype->flags |= BTF_FORTIFICATION;
|
||||||
bld = test_create_building(r, btype);
|
bld = test_create_building(r, btype);
|
||||||
bld->size = 10;
|
bld->size = 10;
|
||||||
|
|
||||||
|
@ -150,10 +159,10 @@ static void test_building_bonus_respects_size(CuTest * tc)
|
||||||
building_type * btype;
|
building_type * btype;
|
||||||
faction * f;
|
faction * f;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
|
btype = setup_castle();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
btype = bt_get_or_create("castle");
|
btype->flags |= BTF_FORTIFICATION;
|
||||||
btype->protection = &add_two;
|
|
||||||
bld = test_create_building(r, btype);
|
bld = test_create_building(r, btype);
|
||||||
bld->size = 10;
|
bld->size = 10;
|
||||||
|
|
||||||
|
@ -178,28 +187,25 @@ static void test_building_bonus_respects_size(CuTest * tc)
|
||||||
|
|
||||||
static void test_building_defence_bonus(CuTest * tc)
|
static void test_building_defence_bonus(CuTest * tc)
|
||||||
{
|
{
|
||||||
unit *au;
|
|
||||||
region *r;
|
|
||||||
building * bld;
|
|
||||||
building_type * btype;
|
building_type * btype;
|
||||||
faction * f;
|
|
||||||
int def;
|
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
r = test_create_region(0, 0, 0);
|
btype = setup_castle();
|
||||||
btype = test_create_buildingtype("castle");
|
|
||||||
btype->protection = (int(*)(const struct building *, const struct unit *, building_bonus))get_function("building_protection");
|
|
||||||
btype->construction->defense_bonus = 3;
|
|
||||||
bld = test_create_building(r, btype);
|
|
||||||
bld->size = 1;
|
|
||||||
|
|
||||||
f = test_create_faction(NULL);
|
btype->maxsize = -1; /* unlimited buildigs get the castle bonus */
|
||||||
au = test_create_unit(f, r);
|
CuAssertIntEquals(tc, 0, building_protection(btype, 0));
|
||||||
scale_number(au, 1);
|
CuAssertIntEquals(tc, 1, building_protection(btype, 1));
|
||||||
u_set_building(au, bld);
|
CuAssertIntEquals(tc, 3, building_protection(btype, 2));
|
||||||
|
CuAssertIntEquals(tc, 5, building_protection(btype, 3));
|
||||||
|
CuAssertIntEquals(tc, 8, building_protection(btype, 4));
|
||||||
|
CuAssertIntEquals(tc, 12, building_protection(btype, 5));
|
||||||
|
CuAssertIntEquals(tc, 12, building_protection(btype, 6));
|
||||||
|
|
||||||
def = btype->protection(bld, au, DEFENSE_BONUS);
|
btype->maxsize = 10; /* limited-size buildings are treated like an E3 watchtower */
|
||||||
CuAssertIntEquals(tc, 3, def);
|
CuAssertIntEquals(tc, 0, building_protection(btype, 0));
|
||||||
|
CuAssertIntEquals(tc, 1, building_protection(btype, 1));
|
||||||
|
CuAssertIntEquals(tc, 2, building_protection(btype, 2));
|
||||||
|
CuAssertIntEquals(tc, 2, building_protection(btype, 3));
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +225,7 @@ static void test_natural_armor(CuTest * tc)
|
||||||
race *rc;
|
race *rc;
|
||||||
unit *u;
|
unit *u;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
rc = test_create_race("human");
|
rc = test_create_race("human");
|
||||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
||||||
set_level(u, SK_STAMINA, 2);
|
set_level(u, SK_STAMINA, 2);
|
||||||
|
@ -244,23 +250,24 @@ static void test_calculate_armor(CuTest * tc)
|
||||||
armor_type *ashield, *achain;
|
armor_type *ashield, *achain;
|
||||||
item_type *ibelt, *ishield, *ichain;
|
item_type *ibelt, *ishield, *ichain;
|
||||||
race *rc;
|
race *rc;
|
||||||
double magres = 0.0;
|
variant magres = frac_zero;
|
||||||
|
variant v50p = frac_make(1, 2);
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
ibelt = it_get_or_create(rt_get_or_create("trollbelt"));
|
ibelt = it_get_or_create(rt_get_or_create("trollbelt"));
|
||||||
ishield = it_get_or_create(rt_get_or_create("shield"));
|
ishield = it_get_or_create(rt_get_or_create("shield"));
|
||||||
ashield = new_armortype(ishield, 0.0, 0.5, 1, ATF_SHIELD);
|
ashield = new_armortype(ishield, 0.0, v50p, 1, ATF_SHIELD);
|
||||||
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
||||||
achain = new_armortype(ichain, 0.0, 0.5, 3, ATF_NONE);
|
achain = new_armortype(ichain, 0.0, v50p, 3, ATF_NONE);
|
||||||
wtype = new_weapontype(it_get_or_create(rt_get_or_create("sword")), 0, 0.5, 0, 0, 0, 0, SK_MELEE, 1);
|
wtype = new_weapontype(it_get_or_create(rt_get_or_create("sword")), 0, v50p, 0, 0, 0, 0, SK_MELEE, 1);
|
||||||
rc = test_create_race("human");
|
rc = test_create_race("human");
|
||||||
du = test_create_unit(test_create_faction(rc), r);
|
du = test_create_unit(test_create_faction(rc), r);
|
||||||
dt.index = 0;
|
dt.index = 0;
|
||||||
|
|
||||||
dt.fighter = setup_fighter(&b, du);
|
dt.fighter = setup_fighter(&b, du);
|
||||||
CuAssertIntEquals_Msg(tc, "default ac", 0, calculate_armor(dt, 0, 0, &magres));
|
CuAssertIntEquals_Msg(tc, "default ac", 0, calculate_armor(dt, 0, 0, &magres));
|
||||||
CuAssertDblEquals_Msg(tc, "magres unmodified", 1.0, magres, 0.01);
|
CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[0], magres.sa[1]);
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
|
@ -293,13 +300,13 @@ static void test_calculate_armor(CuTest * tc)
|
||||||
wtype->flags = WTF_NONE;
|
wtype->flags = WTF_NONE;
|
||||||
|
|
||||||
CuAssertIntEquals_Msg(tc, "magical attack", 3, calculate_armor(dt, 0, 0, &magres));
|
CuAssertIntEquals_Msg(tc, "magical attack", 3, calculate_armor(dt, 0, 0, &magres));
|
||||||
CuAssertDblEquals_Msg(tc, "magres unmodified", 1.0, magres, 0.01);
|
CuAssertIntEquals_Msg(tc, "magres unmodified", magres.sa[1], magres.sa[0]);
|
||||||
|
|
||||||
ashield->flags |= ATF_LAEN;
|
ashield->flags |= ATF_LAEN;
|
||||||
achain->flags |= ATF_LAEN;
|
achain->flags |= ATF_LAEN;
|
||||||
magres = 1.0;
|
magres = frac_one;
|
||||||
CuAssertIntEquals_Msg(tc, "laen armor", 3, calculate_armor(dt, 0, 0, &magres));
|
CuAssertIntEquals_Msg(tc, "laen armor", 3, calculate_armor(dt, 0, 0, &magres));
|
||||||
CuAssertDblEquals_Msg(tc, "laen magres bonus", 0.25, magres, 0.01);
|
CuAssertIntEquals_Msg(tc, "laen magres bonus", 4, magres.sa[1]);
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
@ -313,38 +320,42 @@ static void test_magic_resistance(CuTest *tc)
|
||||||
armor_type *ashield, *achain;
|
armor_type *ashield, *achain;
|
||||||
item_type *ishield, *ichain;
|
item_type *ishield, *ichain;
|
||||||
race *rc;
|
race *rc;
|
||||||
double magres;
|
variant magres;
|
||||||
|
variant v50p = frac_make(1, 2);
|
||||||
|
variant v10p = frac_make(1, 10);
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
ishield = it_get_or_create(rt_get_or_create("shield"));
|
ishield = it_get_or_create(rt_get_or_create("shield"));
|
||||||
ashield = new_armortype(ishield, 0.0, 0.5, 1, ATF_SHIELD);
|
ashield = new_armortype(ishield, 0.0, v50p, 1, ATF_SHIELD);
|
||||||
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
||||||
achain = new_armortype(ichain, 0.0, 0.5, 3, ATF_NONE);
|
achain = new_armortype(ichain, 0.0, v50p, 3, ATF_NONE);
|
||||||
rc = test_create_race("human");
|
rc = test_create_race("human");
|
||||||
du = test_create_unit(test_create_faction(rc), r);
|
du = test_create_unit(test_create_faction(rc), r);
|
||||||
dt.index = 0;
|
dt.index = 0;
|
||||||
|
|
||||||
|
i_change(&du->items, ishield, 1);
|
||||||
dt.fighter = setup_fighter(&b, du);
|
dt.fighter = setup_fighter(&b, du);
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
CuAssertDblEquals_Msg(tc, "no magres bonus", 0.0, magic_resistance(du), 0.01);
|
CuAssertIntEquals_Msg(tc, "no magres reduction", magres.sa[1], magres.sa[0]);
|
||||||
CuAssertDblEquals_Msg(tc, "no magres reduction", 1.0, magres, 0.01);
|
magres = magic_resistance(du);
|
||||||
|
CuAssertIntEquals_Msg(tc, "no magres reduction", 0, magres.sa[0]);
|
||||||
|
|
||||||
ashield->flags |= ATF_LAEN;
|
ashield->flags |= ATF_LAEN;
|
||||||
ashield->magres = 0.1;
|
ashield->magres = v10p;
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
|
CuAssert(tc, "laen reduction => 10%%", frac_equal(frac_make(9, 10), magres));
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
i_change(&du->items, ishield, 1);
|
|
||||||
i_change(&du->items, ichain, 1);
|
i_change(&du->items, ichain, 1);
|
||||||
achain->flags |= ATF_LAEN;
|
achain->flags |= ATF_LAEN;
|
||||||
achain->magres = 0.1;
|
achain->magres = v10p;
|
||||||
ashield->flags |= ATF_LAEN;
|
ashield->flags |= ATF_LAEN;
|
||||||
ashield->magres = 0.1;
|
ashield->magres = v10p;
|
||||||
dt.fighter = setup_fighter(&b, du);
|
dt.fighter = setup_fighter(&b, du);
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
CuAssertDblEquals_Msg(tc, "laen reduction", 0.81, magres, 0.01);
|
CuAssert(tc, "2x laen reduction => 81%%", frac_equal(frac_make(81, 100), magres));
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
|
@ -353,17 +364,20 @@ static void test_magic_resistance(CuTest *tc)
|
||||||
set_level(du, SK_MAGIC, 2);
|
set_level(du, SK_MAGIC, 2);
|
||||||
dt.fighter = setup_fighter(&b, du);
|
dt.fighter = setup_fighter(&b, du);
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
CuAssertDblEquals_Msg(tc, "skill bonus", 0.1, magic_resistance(du), 0.01);
|
CuAssert(tc, "skill reduction => 90%%", frac_equal(magres, frac_make(9, 10)));
|
||||||
CuAssertDblEquals_Msg(tc, "skill reduction", 0.9, magres, 0.01);
|
magres = magic_resistance(du);
|
||||||
rc->magres = 50; /* percentage, gets added to skill bonus */
|
CuAssert(tc, "skill reduction", frac_equal(magres, v10p));
|
||||||
|
rc->magres = v50p; /* percentage, gets added to skill bonus */
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
CuAssertDblEquals_Msg(tc, "race bonus", 0.6, magic_resistance(du), 0.01);
|
CuAssert(tc, "race reduction => 40%%", frac_equal(magres, frac_make(4, 10)));
|
||||||
CuAssertDblEquals_Msg(tc, "race reduction", 0.4, magres, 0.01);
|
magres = magic_resistance(du);
|
||||||
|
CuAssert(tc, "race bonus => 60%%", frac_equal(magres, frac_make(60, 100)));
|
||||||
|
|
||||||
rc->magres = 150; /* should not cause negative damage multiplier */
|
rc->magres = frac_make(15, 10); /* 150% resistance should not cause negative damage multiplier */
|
||||||
CuAssertDblEquals_Msg(tc, "magic resistance is never > 0.9", 0.9, magic_resistance(du), 0.01);
|
magres = magic_resistance(du);
|
||||||
|
CuAssert(tc, "magic resistance is never > 0.9", frac_equal(magres, frac_make(9, 10)));
|
||||||
calculate_armor(dt, 0, 0, &magres);
|
calculate_armor(dt, 0, 0, &magres);
|
||||||
CuAssertDblEquals_Msg(tc, "damage reduction is never < 0.1", 0.1, magres, 0.01);
|
CuAssert(tc, "damage reduction is never < 0.1", frac_equal(magres, frac_make(1, 10)));
|
||||||
|
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
|
@ -379,14 +393,15 @@ static void test_projectile_armor(CuTest * tc)
|
||||||
armor_type *ashield, *achain;
|
armor_type *ashield, *achain;
|
||||||
item_type *ishield, *ichain;
|
item_type *ishield, *ichain;
|
||||||
race *rc;
|
race *rc;
|
||||||
|
variant v50p = frac_make(1, 2);
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
ishield = it_get_or_create(rt_get_or_create("shield"));
|
ishield = it_get_or_create(rt_get_or_create("shield"));
|
||||||
ashield = new_armortype(ishield, 0.0, 0.5, 1, ATF_SHIELD);
|
ashield = new_armortype(ishield, 0.0, v50p, 1, ATF_SHIELD);
|
||||||
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
ichain = it_get_or_create(rt_get_or_create("chainmail"));
|
||||||
achain = new_armortype(ichain, 0.0, 0.5, 3, ATF_NONE);
|
achain = new_armortype(ichain, 0.0, v50p, 3, ATF_NONE);
|
||||||
wtype = new_weapontype(it_get_or_create(rt_get_or_create("sword")), 0, 0.5, 0, 0, 0, 0, SK_MELEE, 1);
|
wtype = new_weapontype(it_get_or_create(rt_get_or_create("sword")), 0, v50p, 0, 0, 0, 0, SK_MELEE, 1);
|
||||||
rc = test_create_race("human");
|
rc = test_create_race("human");
|
||||||
rc->battle_flags |= BF_EQUIPMENT;
|
rc->battle_flags |= BF_EQUIPMENT;
|
||||||
du = test_create_unit(test_create_faction(rc), r);
|
du = test_create_unit(test_create_faction(rc), r);
|
||||||
|
@ -414,7 +429,7 @@ static void test_battle_skilldiff(CuTest *tc)
|
||||||
unit *ua, *ud;
|
unit *ua, *ud;
|
||||||
battle *b = NULL;
|
battle *b = NULL;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
|
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
ud = test_create_unit(test_create_faction(0), r);
|
ud = test_create_unit(test_create_faction(0), r);
|
||||||
|
@ -441,10 +456,6 @@ static void test_battle_skilldiff(CuTest *tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int protect(const building *b, const unit *u, building_bonus bonus) {
|
|
||||||
return (bonus == DEFENSE_BONUS) ? 4 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_battle_skilldiff_building(CuTest *tc)
|
static void test_battle_skilldiff_building(CuTest *tc)
|
||||||
{
|
{
|
||||||
troop ta, td;
|
troop ta, td;
|
||||||
|
@ -454,8 +465,8 @@ static void test_battle_skilldiff_building(CuTest *tc)
|
||||||
building_type *btype;
|
building_type *btype;
|
||||||
const curse_type *strongwall_ct, *magicwalls_ct;
|
const curse_type *strongwall_ct, *magicwalls_ct;
|
||||||
|
|
||||||
test_cleanup();
|
test_setup();
|
||||||
btype = test_create_buildingtype("castle");
|
btype = setup_castle();
|
||||||
strongwall_ct = ct_find("strongwall");
|
strongwall_ct = ct_find("strongwall");
|
||||||
magicwalls_ct = ct_find("magicwalls");
|
magicwalls_ct = ct_find("magicwalls");
|
||||||
|
|
||||||
|
@ -470,14 +481,14 @@ static void test_battle_skilldiff_building(CuTest *tc)
|
||||||
ua = test_create_unit(test_create_faction(0), r);
|
ua = test_create_unit(test_create_faction(0), r);
|
||||||
CuAssertIntEquals(tc, 0, skilldiff(ta, td, 0));
|
CuAssertIntEquals(tc, 0, skilldiff(ta, td, 0));
|
||||||
|
|
||||||
btype->protection = protect;
|
ud->building->size = 10;
|
||||||
CuAssertIntEquals(tc, -4, skilldiff(ta, td, 0));
|
CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0));
|
||||||
|
|
||||||
create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1);
|
create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1);
|
||||||
CuAssertIntEquals(tc, -8, skilldiff(ta, td, 0));
|
CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0));
|
||||||
|
|
||||||
create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1);
|
create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1);
|
||||||
CuAssertIntEquals(tc, -10, skilldiff(ta, td, 0));
|
CuAssertIntEquals(tc, -4, skilldiff(ta, td, 0));
|
||||||
|
|
||||||
free_battle(b);
|
free_battle(b);
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
|
|
|
@ -914,6 +914,10 @@ struct message * get_modifiers(unit *u, const resource_mod *mod, variant *savep,
|
||||||
return NULL;
|
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)
|
static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
{
|
{
|
||||||
const item_type *itype = resource2item(rtype);
|
const item_type *itype = resource2item(rtype);
|
||||||
|
@ -921,8 +925,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
|
||||||
int dm = 0;
|
int dm = 0;
|
||||||
allocation_list *alist;
|
allocation_list *alist;
|
||||||
allocation *al;
|
allocation *al;
|
||||||
attrib *a = a_find(rtype->attribs, &at_resourcelimit);
|
resource_limit *rdata = get_resourcelimit(rtype);
|
||||||
resource_limit *rdata = (resource_limit *)a->data.v;
|
|
||||||
const resource_type *rring;
|
const resource_type *rring;
|
||||||
int amount, skill, skill_mod = 0;
|
int amount, skill, skill_mod = 0;
|
||||||
variant save_mod;
|
variant save_mod;
|
||||||
|
@ -1119,9 +1122,8 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
|
||||||
{
|
{
|
||||||
allocation *al;
|
allocation *al;
|
||||||
int nreq = 0;
|
int nreq = 0;
|
||||||
attrib *a = a_find(rtype->attribs, &at_resourcelimit);
|
resource_limit *rdata = get_resourcelimit(rtype);
|
||||||
resource_limit *rdata = (resource_limit *)a->data.v;
|
int avail = 0;
|
||||||
int avail = rdata->value;
|
|
||||||
|
|
||||||
for (al = alist; al; al = al->next) {
|
for (al = alist; al; al = al->next) {
|
||||||
nreq += required(al->want, al->save);
|
nreq += required(al->want, al->save);
|
||||||
|
@ -1160,11 +1162,10 @@ typedef void(*allocate_function) (const resource_type *, struct region *,
|
||||||
|
|
||||||
static allocate_function get_allocator(const struct resource_type *rtype)
|
static allocate_function get_allocator(const struct resource_type *rtype)
|
||||||
{
|
{
|
||||||
attrib *a = a_find(rtype->attribs, &at_resourcelimit);
|
resource_limit *rdata = get_resourcelimit(rtype);
|
||||||
|
|
||||||
if (a != NULL) {
|
if (rdata) {
|
||||||
resource_limit *rdata = (resource_limit *)a->data.v;
|
if (rdata->limit != NULL) {
|
||||||
if (rdata->value > 0 || rdata->limit != NULL) {
|
|
||||||
return attrib_allocation;
|
return attrib_allocation;
|
||||||
}
|
}
|
||||||
return leveled_allocation;
|
return leveled_allocation;
|
||||||
|
|
|
@ -211,7 +211,7 @@ static void test_tax_cmd(CuTest *tc) {
|
||||||
silver = get_resourcetype(R_SILVER)->itype;
|
silver = get_resourcetype(R_SILVER)->itype;
|
||||||
|
|
||||||
sword = it_get_or_create(rt_get_or_create("sword"));
|
sword = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(sword, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 1);
|
new_weapontype(sword, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 1);
|
||||||
i_change(&u->items, sword, 1);
|
i_change(&u->items, sword, 1);
|
||||||
set_level(u, SK_MELEE, 1);
|
set_level(u, SK_MELEE, 1);
|
||||||
|
|
||||||
|
@ -348,7 +348,6 @@ static void test_make_item(CuTest *tc) {
|
||||||
struct item_type *itype;
|
struct item_type *itype;
|
||||||
const struct resource_type *rt_silver;
|
const struct resource_type *rt_silver;
|
||||||
resource_type *rtype;
|
resource_type *rtype;
|
||||||
attrib *a;
|
|
||||||
resource_limit *rdata;
|
resource_limit *rdata;
|
||||||
double d = 0.6;
|
double d = 0.6;
|
||||||
|
|
||||||
|
@ -382,10 +381,8 @@ static void test_make_item(CuTest *tc) {
|
||||||
free(itype->construction->materials);
|
free(itype->construction->materials);
|
||||||
itype->construction->materials = 0;
|
itype->construction->materials = 0;
|
||||||
rtype->flags |= RTF_LIMITED;
|
rtype->flags |= RTF_LIMITED;
|
||||||
a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
|
rmt_create(rtype);
|
||||||
rdata = (resource_limit *)a->data.v;
|
rdata = rtype->limit = calloc(1, sizeof(resource_limit));
|
||||||
rdata->value = 0;
|
|
||||||
rmt_create(rtype, "stone");
|
|
||||||
add_resource(u->region, 1, 300, 150, rtype);
|
add_resource(u->region, 1, 300, 150, rtype);
|
||||||
u->region->resources->amount = 300; /* there are 300 stones at level 1 */
|
u->region->resources->amount = 300; /* there are 300 stones at level 1 */
|
||||||
set_level(u, SK_ALCHEMY, 10);
|
set_level(u, SK_ALCHEMY, 10);
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
#include <kernel/xmlreader.h>
|
#include <kernel/xmlreader.h>
|
||||||
#include <modules/gmcmd.h>
|
#include <modules/gmcmd.h>
|
||||||
#include <modules/xmas.h>
|
#include <modules/xmas.h>
|
||||||
#include <items/itemtypes.h>
|
#include <items/xerewards.h>
|
||||||
|
#include <items/weapons.h>
|
||||||
|
|
||||||
#include <attributes/attributes.h>
|
#include <attributes/attributes.h>
|
||||||
#include <util/message.h>
|
#include <util/message.h>
|
||||||
#include <races/races.h>
|
#include <races/races.h>
|
||||||
|
@ -81,7 +83,8 @@ void game_init(void)
|
||||||
#endif
|
#endif
|
||||||
wormholes_register();
|
wormholes_register();
|
||||||
|
|
||||||
register_itemtypes();
|
register_weapons();
|
||||||
|
register_xerewards();
|
||||||
#ifdef USE_LIBXML2
|
#ifdef USE_LIBXML2
|
||||||
register_xmlreader();
|
register_xmlreader();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
|
|
||||||
#include <attributes/attributes.h>
|
#include <attributes/attributes.h>
|
||||||
#include <triggers/triggers.h>
|
#include <triggers/triggers.h>
|
||||||
#include <items/itemtypes.h>
|
|
||||||
|
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
#include <util/unicode.h>
|
#include <util/unicode.h>
|
||||||
|
|
|
@ -42,7 +42,7 @@ static void test_guard_unskilled(CuTest * tc)
|
||||||
|
|
||||||
test_setup();
|
test_setup();
|
||||||
itype = it_get_or_create(rt_get_or_create("sword"));
|
itype = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2);
|
new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 2);
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
u = test_create_unit(test_create_faction(0), r);
|
u = test_create_unit(test_create_faction(0), r);
|
||||||
ug = test_create_unit(test_create_faction(0), r);
|
ug = test_create_unit(test_create_faction(0), r);
|
||||||
|
@ -61,7 +61,7 @@ static void test_guard_armed(CuTest * tc)
|
||||||
|
|
||||||
test_setup();
|
test_setup();
|
||||||
itype = it_get_or_create(rt_get_or_create("sword"));
|
itype = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2);
|
new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 2);
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
u = test_create_unit(test_create_faction(0), r);
|
u = test_create_unit(test_create_faction(0), r);
|
||||||
ug = test_create_unit(test_create_faction(0), r);
|
ug = test_create_unit(test_create_faction(0), r);
|
||||||
|
@ -80,7 +80,7 @@ static void test_is_guard(CuTest * tc)
|
||||||
|
|
||||||
test_setup();
|
test_setup();
|
||||||
itype = it_get_or_create(rt_get_or_create("sword"));
|
itype = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2);
|
new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 2);
|
||||||
r = test_create_region(0, 0, 0);
|
r = test_create_region(0, 0, 0);
|
||||||
ug = test_create_unit(test_create_faction(0), r);
|
ug = test_create_unit(test_create_faction(0), r);
|
||||||
i_change(&ug->items, itype, 1);
|
i_change(&ug->items, itype, 1);
|
||||||
|
|
|
@ -5,10 +5,7 @@ xerewards.test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(_FILES
|
SET(_FILES
|
||||||
artrewards.c
|
|
||||||
demonseye.c
|
demonseye.c
|
||||||
itemtypes.c
|
|
||||||
seed.c
|
|
||||||
speedsail.c
|
speedsail.c
|
||||||
weapons.c
|
weapons.c
|
||||||
xerewards.c
|
xerewards.c
|
||||||
|
|
|
@ -1,155 +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 "artrewards.h"
|
|
||||||
|
|
||||||
/* kernel includes */
|
|
||||||
#include <kernel/item.h>
|
|
||||||
#include <kernel/pool.h>
|
|
||||||
#include <kernel/region.h>
|
|
||||||
#include <kernel/faction.h>
|
|
||||||
#include <kernel/unit.h>
|
|
||||||
#include <kernel/curse.h>
|
|
||||||
#include <kernel/messages.h>
|
|
||||||
#include <kernel/ship.h>
|
|
||||||
|
|
||||||
/* util includes */
|
|
||||||
#include <util/attrib.h>
|
|
||||||
#include <util/rand.h>
|
|
||||||
|
|
||||||
/* libc includes */
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define HORNRANGE 10
|
|
||||||
#define HORNDURATION 3
|
|
||||||
#define HORNIMMUNITY 30
|
|
||||||
|
|
||||||
static int age_peaceimmune(attrib * a, void *owner)
|
|
||||||
{
|
|
||||||
UNUSED_ARG(owner);
|
|
||||||
return (--a->data.i > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static attrib_type at_peaceimmune = {
|
|
||||||
"peaceimmune",
|
|
||||||
NULL, NULL,
|
|
||||||
age_peaceimmune,
|
|
||||||
a_writeint,
|
|
||||||
a_readint
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
use_hornofdancing(struct unit *u, const struct item_type *itype,
|
|
||||||
int amount, struct order *ord)
|
|
||||||
{
|
|
||||||
region *r;
|
|
||||||
int regionsPacified = 0;
|
|
||||||
|
|
||||||
for (r = regions; r; r = r->next) {
|
|
||||||
if (distance(u->region, r) < HORNRANGE) {
|
|
||||||
if (a_find(r->attribs, &at_peaceimmune) == NULL) {
|
|
||||||
attrib *a;
|
|
||||||
|
|
||||||
create_curse(u, &r->attribs, ct_find("peacezone"),
|
|
||||||
20, HORNDURATION, 1.0, 0);
|
|
||||||
|
|
||||||
a = a_add(&r->attribs, a_new(&at_peaceimmune));
|
|
||||||
a->data.i = HORNIMMUNITY;
|
|
||||||
|
|
||||||
ADDMSG(&r->msgs, msg_message("hornofpeace_r_success",
|
|
||||||
"unit region", u, u->region));
|
|
||||||
|
|
||||||
regionsPacified++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ADDMSG(&r->msgs, msg_message("hornofpeace_r_nosuccess",
|
|
||||||
"unit region", u, u->region));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (regionsPacified > 0) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "hornofpeace_u_success",
|
|
||||||
"pacified", regionsPacified));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "hornofpeace_u_nosuccess",
|
|
||||||
""));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SPEEDUP 2
|
|
||||||
|
|
||||||
static int
|
|
||||||
useonother_trappedairelemental(struct unit *u, int shipId,
|
|
||||||
const struct item_type *itype, int amount, struct order *ord)
|
|
||||||
{
|
|
||||||
curse *c;
|
|
||||||
ship *sh;
|
|
||||||
|
|
||||||
if (shipId <= 0) {
|
|
||||||
cmistake(u, ord, 20, MSG_MOVE);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sh = findshipr(u->region, shipId);
|
|
||||||
if (!sh) {
|
|
||||||
cmistake(u, ord, 20, MSG_MOVE);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c =
|
|
||||||
create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, SPEEDUP,
|
|
||||||
0);
|
|
||||||
c_setflag(c, CURSE_NOAGE);
|
|
||||||
|
|
||||||
ADDMSG(&u->faction->msgs, msg_message("trappedairelemental_success",
|
|
||||||
"unit region command ship", u, u->region, ord, sh));
|
|
||||||
|
|
||||||
use_pooled(u, itype->rtype, GET_DEFAULT, 1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
use_trappedairelemental(struct unit *u,
|
|
||||||
const struct item_type *itype, int amount, struct order *ord)
|
|
||||||
{
|
|
||||||
ship *sh = u->ship;
|
|
||||||
|
|
||||||
if (sh == NULL) {
|
|
||||||
cmistake(u, ord, 20, MSG_MOVE);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return useonother_trappedairelemental(u, sh->no, itype, amount, ord);
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_artrewards(void)
|
|
||||||
{
|
|
||||||
at_register(&at_peaceimmune);
|
|
||||||
register_item_use(use_hornofdancing, "use_hornofdancing");
|
|
||||||
register_item_use(use_trappedairelemental, "use_trappedairelemental");
|
|
||||||
register_item_useonother(useonother_trappedairelemental,
|
|
||||||
"useonother_trappedairelemental");
|
|
||||||
}
|
|
|
@ -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_ARTREWARDS
|
|
||||||
#define H_ITM_ARTREWARDS
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void register_artrewards(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
| | Enno Rehling <enno@eressea.de>
|
|
||||||
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
|
|
||||||
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
|
|
||||||
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
|
|
||||||
+-------------------+ Stefan Reich <reich@halbling.de>
|
|
||||||
|
|
||||||
This program may not be used, modified or distributed
|
|
||||||
without prior permission by the authors of Eressea.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <platform.h>
|
|
||||||
#include "itemtypes.h"
|
|
||||||
|
|
||||||
#include "xerewards.h"
|
|
||||||
#include "artrewards.h"
|
|
||||||
#include "weapons.h"
|
|
||||||
#include "seed.h"
|
|
||||||
|
|
||||||
void register_itemtypes(void)
|
|
||||||
{
|
|
||||||
/* registering misc. functions */
|
|
||||||
register_weapons();
|
|
||||||
register_xerewards();
|
|
||||||
register_artrewards();
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_itemtypes(void)
|
|
||||||
{
|
|
||||||
init_seed();
|
|
||||||
init_mallornseed();
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
||||||
| | Enno Rehling <enno@eressea.de>
|
|
||||||
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
|
|
||||||
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
|
|
||||||
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
|
|
||||||
+-------------------+ Stefan Reich <reich@halbling.de>
|
|
||||||
|
|
||||||
This program may not be used, modified or distributed
|
|
||||||
without prior permission by the authors of Eressea.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef H_ITM_ITEMS
|
|
||||||
#define H_ITM_ITEMS
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void init_itemtypes(void);
|
|
||||||
extern void register_itemtypes(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,97 +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 "seed.h"
|
|
||||||
|
|
||||||
/* kernel includes */
|
|
||||||
#include <kernel/build.h>
|
|
||||||
#include <kernel/item.h>
|
|
||||||
#include <kernel/region.h>
|
|
||||||
|
|
||||||
/* util includes */
|
|
||||||
#include <util/attrib.h>
|
|
||||||
#include <util/functions.h>
|
|
||||||
|
|
||||||
/* libc includes */
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
static void produce_seeds(region * r, const resource_type * rtype, int norders)
|
|
||||||
{
|
|
||||||
assert(r->land && r->land->trees[0] >= norders);
|
|
||||||
r->land->trees[0] -= norders;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int limit_seeds(const region * r, const resource_type * rtype)
|
|
||||||
{
|
|
||||||
if ((r->flags & RF_MALLORN)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return r->land ? r->land->trees[0] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_seed(void)
|
|
||||||
{
|
|
||||||
attrib *a;
|
|
||||||
resource_limit *rdata;
|
|
||||||
resource_type *rtype;
|
|
||||||
|
|
||||||
rtype = rt_find("seed");
|
|
||||||
if (rtype != NULL) {
|
|
||||||
a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
|
|
||||||
rdata = (resource_limit *)a->data.v;
|
|
||||||
rdata->limit = limit_seeds;
|
|
||||||
rdata->produce = produce_seeds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mallorn */
|
|
||||||
|
|
||||||
static void
|
|
||||||
produce_mallornseeds(region * r, const resource_type * rtype, int norders)
|
|
||||||
{
|
|
||||||
assert(r->flags & RF_MALLORN);
|
|
||||||
r->land->trees[0] -= norders;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int limit_mallornseeds(const region * r, const resource_type * rtype)
|
|
||||||
{
|
|
||||||
if (!(r->flags & RF_MALLORN)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return r->land ? r->land->trees[0] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_mallornseed(void)
|
|
||||||
{
|
|
||||||
attrib *a;
|
|
||||||
resource_limit *rdata;
|
|
||||||
resource_type *rtype;
|
|
||||||
|
|
||||||
rtype = rt_find("mallornseed");
|
|
||||||
if (rtype != NULL) {
|
|
||||||
rtype->flags |= RTF_LIMITED;
|
|
||||||
rtype->flags |= RTF_POOLED;
|
|
||||||
|
|
||||||
a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
|
|
||||||
rdata = (resource_limit *)a->data.v;
|
|
||||||
rdata->limit = limit_mallornseeds;
|
|
||||||
rdata->produce = produce_mallornseeds;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +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_SEED
|
|
||||||
#define H_ITM_SEED
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void init_seed(void);
|
|
||||||
extern void init_mallornseed(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -45,9 +45,6 @@ extern "C" {
|
||||||
|
|
||||||
int maxsize; /* maximum size of this type */
|
int maxsize; /* maximum size of this type */
|
||||||
int reqsize; /* size of object using up 1 set of requirement. */
|
int reqsize; /* size of object using up 1 set of requirement. */
|
||||||
int defense_bonus; /* protection bonus (defense) during combat */
|
|
||||||
int close_combat_bonus; /* close combat attack bonus*/
|
|
||||||
int ranged_bonus; /* ranged attack bonus */
|
|
||||||
requirement *materials; /* material req'd to build one object */
|
requirement *materials; /* material req'd to build one object */
|
||||||
const struct building_type *btype;
|
const struct building_type *btype;
|
||||||
/* building type required to make this thing */
|
/* building type required to make this thing */
|
||||||
|
|
|
@ -325,8 +325,13 @@ const building_type *findbuildingtype(const char *name,
|
||||||
building_type *btype = (building_type *)selist_get(ql, qi);
|
building_type *btype = (building_type *)selist_get(ql, qi);
|
||||||
|
|
||||||
const char *n = LOC(lang, btype->_name);
|
const char *n = LOC(lang, btype->_name);
|
||||||
type.v = (void *)btype;
|
if (!n) {
|
||||||
addtoken((struct tnode **)&bn->names, n, type);
|
log_error("building type %s has no translation in %s",
|
||||||
|
btype->_name, locale_name(lang));
|
||||||
|
} else {
|
||||||
|
type.v = (void *)btype;
|
||||||
|
addtoken((struct tnode **)&bn->names, n, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bnames = bn;
|
bnames = bn;
|
||||||
}
|
}
|
||||||
|
@ -337,40 +342,24 @@ const building_type *findbuildingtype(const char *name,
|
||||||
|
|
||||||
int cmp_castle_size(const building * b, const building * a)
|
int cmp_castle_size(const building * b, const building * a)
|
||||||
{
|
{
|
||||||
if (!b || !b->type->protection || !building_owner(b)) {
|
if (!b || !(b->type->flags & BTF_FORTIFICATION) || !building_owner(b)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!a || !a->type->protection || !building_owner(a)) {
|
if (!a || !(a->type->flags & BTF_FORTIFICATION) || !building_owner(a)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return b->size - a->size;
|
return b->size - a->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int building_protection(const building * b, const unit * u, building_bonus bonus)
|
static const int castle_bonus[6] = { 0, 1, 3, 5, 8, 12 };
|
||||||
|
static const int watch_bonus[3] = { 0, 1, 2 };
|
||||||
|
|
||||||
|
int building_protection(const building_type * btype, int stage)
|
||||||
{
|
{
|
||||||
int i = 0;
|
if (btype->maxsize < 0) {
|
||||||
int bsize = buildingeffsize(b, false);
|
return castle_bonus[MIN(stage, 5)];
|
||||||
const construction *cons = b->type->construction;
|
|
||||||
if (!cons) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < bsize; i++)
|
|
||||||
{
|
|
||||||
cons = cons->improvement;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bonus)
|
|
||||||
{
|
|
||||||
case DEFENSE_BONUS:
|
|
||||||
return cons->defense_bonus;
|
|
||||||
case CLOSE_COMBAT_ATTACK_BONUS:
|
|
||||||
return cons->close_combat_bonus;
|
|
||||||
case RANGED_ATTACK_BONUS:
|
|
||||||
return cons->ranged_bonus;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return watch_bonus[MIN(stage, 2)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_building_reference(const struct building *b, struct storage *store)
|
void write_building_reference(const struct building *b, struct storage *store)
|
||||||
|
@ -925,8 +914,6 @@ int cmp_current_owner(const building * b, const building * a)
|
||||||
void register_buildings(void)
|
void register_buildings(void)
|
||||||
{
|
{
|
||||||
register_function((pf_generic)minimum_wage, "minimum_wage");
|
register_function((pf_generic)minimum_wage, "minimum_wage");
|
||||||
register_function((pf_generic)building_protection,
|
|
||||||
"building_protection");
|
|
||||||
register_function((pf_generic)init_smithy, "init_smithy");
|
register_function((pf_generic)init_smithy, "init_smithy");
|
||||||
register_function((pf_generic)castle_name, "castle_name");
|
register_function((pf_generic)castle_name, "castle_name");
|
||||||
register_function((pf_generic)castle_name_2, "castle_name_2");
|
register_function((pf_generic)castle_name_2, "castle_name_2");
|
||||||
|
|
|
@ -51,13 +51,7 @@ extern "C" {
|
||||||
#define BTF_MAGIC 0x40 /* magical effect */
|
#define BTF_MAGIC 0x40 /* magical effect */
|
||||||
#define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */
|
#define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */
|
||||||
#define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */
|
#define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */
|
||||||
#define BTF_FORTIFICATION 0x200 /* safe from monsters */
|
#define BTF_FORTIFICATION 0x200 /* building_protection, safe from monsters */
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DEFENSE_BONUS,
|
|
||||||
CLOSE_COMBAT_ATTACK_BONUS, /* TODO: only DEFENSE_BONUS is in use? */
|
|
||||||
RANGED_ATTACK_BONUS
|
|
||||||
} building_bonus;
|
|
||||||
|
|
||||||
typedef struct building_type {
|
typedef struct building_type {
|
||||||
char *_name;
|
char *_name;
|
||||||
|
@ -66,7 +60,7 @@ extern "C" {
|
||||||
int capacity; /* Kapazit<69>t pro Gr<47><72>enpunkt */
|
int capacity; /* Kapazit<69>t pro Gr<47><72>enpunkt */
|
||||||
int maxcapacity; /* Max. Kapazit<69>t */
|
int maxcapacity; /* Max. Kapazit<69>t */
|
||||||
int maxsize; /* how big can it get, with all the extensions? */
|
int maxsize; /* how big can it get, with all the extensions? */
|
||||||
int magres; /* how well it resists against spells */
|
variant magres; /* how well it resists against spells */
|
||||||
int magresbonus; /* bonus it gives the target against spells */
|
int magresbonus; /* bonus it gives the target against spells */
|
||||||
int fumblebonus; /* bonus that reduces fumbling */
|
int fumblebonus; /* bonus that reduces fumbling */
|
||||||
double auraregen; /* modifier for aura regeneration inside building */
|
double auraregen; /* modifier for aura regeneration inside building */
|
||||||
|
@ -77,7 +71,6 @@ extern "C" {
|
||||||
const struct building * b, int size);
|
const struct building * b, int size);
|
||||||
void(*init) (struct building_type *);
|
void(*init) (struct building_type *);
|
||||||
void(*age) (struct building *);
|
void(*age) (struct building *);
|
||||||
int(*protection) (const struct building *, const struct unit *, building_bonus bonus);
|
|
||||||
double(*taxes) (const struct building *, int size);
|
double(*taxes) (const struct building *, int size);
|
||||||
struct attrib *attribs;
|
struct attrib *attribs;
|
||||||
} building_type;
|
} building_type;
|
||||||
|
@ -85,8 +78,8 @@ extern "C" {
|
||||||
extern struct selist *buildingtypes;
|
extern struct selist *buildingtypes;
|
||||||
extern struct attrib_type at_building_action;
|
extern struct attrib_type at_building_action;
|
||||||
|
|
||||||
int cmp_castle_size(const struct building * b, const struct building * a);
|
int cmp_castle_size(const struct building *b, const struct building *a);
|
||||||
int building_protection(const struct building * b, const struct unit * u, building_bonus bonus);
|
int building_protection(const struct building_type *btype, int stage);
|
||||||
building_type *bt_get_or_create(const char *name);
|
building_type *bt_get_or_create(const char *name);
|
||||||
bool bt_changed(int *cache);
|
bool bt_changed(int *cache);
|
||||||
const building_type *bt_find(const char *name);
|
const building_type *bt_find(const char *name);
|
||||||
|
|
|
@ -376,13 +376,12 @@ static void test_btype_defaults(CuTest *tc) {
|
||||||
CuAssertTrue(tc, !btype->name);
|
CuAssertTrue(tc, !btype->name);
|
||||||
CuAssertTrue(tc, !btype->init);
|
CuAssertTrue(tc, !btype->init);
|
||||||
CuAssertTrue(tc, !btype->age);
|
CuAssertTrue(tc, !btype->age);
|
||||||
CuAssertTrue(tc, !btype->protection);
|
|
||||||
CuAssertTrue(tc, !btype->taxes);
|
CuAssertTrue(tc, !btype->taxes);
|
||||||
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);
|
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);
|
||||||
CuAssertIntEquals(tc, -1, btype->maxsize);
|
CuAssertIntEquals(tc, -1, btype->maxsize);
|
||||||
CuAssertIntEquals(tc, 1, btype->capacity);
|
CuAssertIntEquals(tc, 1, btype->capacity);
|
||||||
CuAssertIntEquals(tc, -1, btype->maxcapacity);
|
CuAssertIntEquals(tc, -1, btype->maxcapacity);
|
||||||
CuAssertIntEquals(tc, 0, btype->magres);
|
CuAssertIntEquals(tc, 0, btype->magres.sa[0]);
|
||||||
CuAssertIntEquals(tc, 0, btype->magresbonus);
|
CuAssertIntEquals(tc, 0, btype->magresbonus);
|
||||||
CuAssertIntEquals(tc, 0, btype->fumblebonus);
|
CuAssertIntEquals(tc, 0, btype->fumblebonus);
|
||||||
CuAssertIntEquals(tc, 0, btype->flags);
|
CuAssertIntEquals(tc, 0, btype->flags);
|
||||||
|
@ -515,6 +514,31 @@ static void test_cmp_castle_size(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_building_effsize(CuTest *tc) {
|
||||||
|
building *b;
|
||||||
|
building_type *btype;
|
||||||
|
construction *cons;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
btype = bt_get_or_create("castle");
|
||||||
|
cons = btype->construction = calloc(1, sizeof(construction));
|
||||||
|
cons->maxsize = 5;
|
||||||
|
cons = cons->improvement = calloc(1, sizeof(construction));
|
||||||
|
cons->maxsize = 5;
|
||||||
|
cons = cons->improvement = calloc(1, sizeof(construction));
|
||||||
|
cons->maxsize = -1;
|
||||||
|
b = test_create_building(test_create_region(0,0,0), btype);
|
||||||
|
b->size = 1;
|
||||||
|
CuAssertIntEquals(tc, 0, buildingeffsize(b, false));
|
||||||
|
b->size = 5;
|
||||||
|
CuAssertIntEquals(tc, 1, buildingeffsize(b, false));
|
||||||
|
b->size = 10;
|
||||||
|
CuAssertIntEquals(tc, 2, buildingeffsize(b, false));
|
||||||
|
b->size = 20;
|
||||||
|
CuAssertIntEquals(tc, 2, buildingeffsize(b, false));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_building_suite(void)
|
CuSuite *get_building_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -522,6 +546,7 @@ CuSuite *get_building_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_register_building);
|
SUITE_ADD_TEST(suite, test_register_building);
|
||||||
SUITE_ADD_TEST(suite, test_btype_defaults);
|
SUITE_ADD_TEST(suite, test_btype_defaults);
|
||||||
SUITE_ADD_TEST(suite, test_building_set_owner);
|
SUITE_ADD_TEST(suite, test_building_set_owner);
|
||||||
|
SUITE_ADD_TEST(suite, test_building_effsize);
|
||||||
SUITE_ADD_TEST(suite, test_buildingowner_resets_when_empty);
|
SUITE_ADD_TEST(suite, test_buildingowner_resets_when_empty);
|
||||||
SUITE_ADD_TEST(suite, test_buildingowner_goes_to_next_when_empty);
|
SUITE_ADD_TEST(suite, test_buildingowner_goes_to_next_when_empty);
|
||||||
SUITE_ADD_TEST(suite, test_buildingowner_goes_to_other_when_empty);
|
SUITE_ADD_TEST(suite, test_buildingowner_goes_to_other_when_empty);
|
||||||
|
|
|
@ -275,7 +275,7 @@ luxury_type *new_luxurytype(item_type * itype, int price)
|
||||||
}
|
}
|
||||||
|
|
||||||
weapon_type *new_weapontype(item_type * itype,
|
weapon_type *new_weapontype(item_type * itype,
|
||||||
int wflags, double magres, const char *damage[], int offmod, int defmod,
|
int wflags, variant magres, const char *damage[], int offmod, int defmod,
|
||||||
int reload, skill_t sk, int minskill)
|
int reload, skill_t sk, int minskill)
|
||||||
{
|
{
|
||||||
weapon_type *wtype;
|
weapon_type *wtype;
|
||||||
|
@ -301,7 +301,7 @@ weapon_type *new_weapontype(item_type * itype,
|
||||||
return wtype;
|
return wtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
armor_type *new_armortype(item_type * itype, double penalty, double magres,
|
armor_type *new_armortype(item_type * itype, double penalty, variant magres,
|
||||||
int prot, unsigned int flags)
|
int prot, unsigned int flags)
|
||||||
{
|
{
|
||||||
armor_type *atype;
|
armor_type *atype;
|
||||||
|
@ -1159,22 +1159,6 @@ const item_type *finditemtype(const char *name, const struct locale *lang)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_resourcelimit(attrib * a)
|
|
||||||
{
|
|
||||||
a->data.v = calloc(sizeof(resource_limit), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void finalize_resourcelimit(attrib * a)
|
|
||||||
{
|
|
||||||
free(a->data.v);
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib_type at_resourcelimit = {
|
|
||||||
"resourcelimit",
|
|
||||||
init_resourcelimit,
|
|
||||||
finalize_resourcelimit,
|
|
||||||
};
|
|
||||||
|
|
||||||
item *item_spoil(const struct race *rc, int size)
|
item *item_spoil(const struct race *rc, int size)
|
||||||
{
|
{
|
||||||
item *itm = NULL;
|
item *itm = NULL;
|
||||||
|
@ -1258,6 +1242,9 @@ void free_rtype(resource_type *rtype) {
|
||||||
if (rtype->itype) {
|
if (rtype->itype) {
|
||||||
free_itype(rtype->itype);
|
free_itype(rtype->itype);
|
||||||
}
|
}
|
||||||
|
if (rtype->raw) {
|
||||||
|
free(rtype->raw);
|
||||||
|
}
|
||||||
free(rtype->_name);
|
free(rtype->_name);
|
||||||
free(rtype);
|
free(rtype);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
||||||
struct unit;
|
struct unit;
|
||||||
struct attrib;
|
struct attrib;
|
||||||
struct attrib_type;
|
struct attrib_type;
|
||||||
|
struct race;
|
||||||
struct region;
|
struct region;
|
||||||
struct resource_type;
|
struct resource_type;
|
||||||
struct locale;
|
struct locale;
|
||||||
|
@ -37,6 +38,8 @@ extern "C" {
|
||||||
struct order;
|
struct order;
|
||||||
struct storage;
|
struct storage;
|
||||||
struct gamedata;
|
struct gamedata;
|
||||||
|
struct rawmaterial_type;
|
||||||
|
struct resource_limit;
|
||||||
|
|
||||||
typedef struct item {
|
typedef struct item {
|
||||||
struct item *next;
|
struct item *next;
|
||||||
|
@ -76,6 +79,8 @@ extern "C" {
|
||||||
rtype_uchange uchange;
|
rtype_uchange uchange;
|
||||||
rtype_uget uget;
|
rtype_uget uget;
|
||||||
rtype_name name;
|
rtype_name name;
|
||||||
|
struct rawmaterial_type *raw;
|
||||||
|
struct resource_limit *limit;
|
||||||
/* --- pointers --- */
|
/* --- pointers --- */
|
||||||
struct attrib *attribs;
|
struct attrib *attribs;
|
||||||
struct item_type *itype;
|
struct item_type *itype;
|
||||||
|
@ -94,25 +99,6 @@ extern "C" {
|
||||||
#define RMF_SAVEMATERIAL 0x02 /* fraction (sa[0]/sa[1]), multiplier on resource usage */
|
#define RMF_SAVEMATERIAL 0x02 /* fraction (sa[0]/sa[1]), multiplier on resource usage */
|
||||||
#define RMF_REQUIREDBUILDING 0x04 /* building, required to build */
|
#define RMF_REQUIREDBUILDING 0x04 /* building, required to build */
|
||||||
|
|
||||||
typedef struct resource_mod {
|
|
||||||
variant value;
|
|
||||||
const struct building_type *btype;
|
|
||||||
const struct race *race;
|
|
||||||
unsigned int flags;
|
|
||||||
} resource_mod;
|
|
||||||
|
|
||||||
extern struct attrib_type at_resourcelimit;
|
|
||||||
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_limit {
|
|
||||||
rlimit_limit limit;
|
|
||||||
rlimit_produce produce;
|
|
||||||
int value;
|
|
||||||
resource_mod *modifiers;
|
|
||||||
} resource_limit;
|
|
||||||
|
|
||||||
/* bitfield values for item_type::flags */
|
/* bitfield values for item_type::flags */
|
||||||
#define ITF_NONE 0x0000
|
#define ITF_NONE 0x0000
|
||||||
#define ITF_HERB 0x0001 /* this item is a herb */
|
#define ITF_HERB 0x0001 /* this item is a herb */
|
||||||
|
@ -195,7 +181,7 @@ extern "C" {
|
||||||
const item_type *itype;
|
const item_type *itype;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
double penalty;
|
double penalty;
|
||||||
double magres;
|
variant magres;
|
||||||
int prot;
|
int prot;
|
||||||
float projectile; /* chance, dass ein projektil abprallt */
|
float projectile; /* chance, dass ein projektil abprallt */
|
||||||
} armor_type;
|
} armor_type;
|
||||||
|
@ -219,7 +205,7 @@ extern "C" {
|
||||||
int minskill;
|
int minskill;
|
||||||
int offmod;
|
int offmod;
|
||||||
int defmod;
|
int defmod;
|
||||||
double magres;
|
variant magres;
|
||||||
int reload; /* time to reload this weapon */
|
int reload; /* time to reload this weapon */
|
||||||
weapon_mod *modifiers;
|
weapon_mod *modifiers;
|
||||||
/* --- functions --- */
|
/* --- functions --- */
|
||||||
|
@ -258,14 +244,12 @@ extern "C" {
|
||||||
/* creation */
|
/* creation */
|
||||||
resource_type *rt_get_or_create(const char *name);
|
resource_type *rt_get_or_create(const char *name);
|
||||||
item_type *it_get_or_create(resource_type *rtype);
|
item_type *it_get_or_create(resource_type *rtype);
|
||||||
item_type *new_itemtype(resource_type * rtype, int iflags, int weight,
|
|
||||||
int capacity);
|
|
||||||
luxury_type *new_luxurytype(item_type * itype, int price);
|
luxury_type *new_luxurytype(item_type * itype, int price);
|
||||||
weapon_type *new_weapontype(item_type * itype, int wflags,
|
weapon_type *new_weapontype(item_type * itype, int wflags,
|
||||||
double magres, const char *damage[], int offmod, int defmod, int reload,
|
variant magres, const char *damage[], int offmod, int defmod, int reload,
|
||||||
skill_t sk, int minskill);
|
skill_t sk, int minskill);
|
||||||
armor_type *new_armortype(item_type * itype, double penalty,
|
armor_type *new_armortype(item_type * itype, double penalty,
|
||||||
double magres, int prot, unsigned int flags);
|
variant magres, int prot, unsigned int flags);
|
||||||
potion_type *new_potiontype(item_type * itype, int level);
|
potion_type *new_potiontype(item_type * itype, int level);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -460,7 +460,7 @@ static void json_race(cJSON *json, race *rc) {
|
||||||
break;
|
break;
|
||||||
case cJSON_Number:
|
case cJSON_Number:
|
||||||
if (strcmp(child->string, "magres") == 0) {
|
if (strcmp(child->string, "magres") == 0) {
|
||||||
rc->magres = child->valueint;
|
rc->magres = frac_make(child->valueint, 100);
|
||||||
}
|
}
|
||||||
else if (strcmp(child->string, "maxaura") == 0) {
|
else if (strcmp(child->string, "maxaura") == 0) {
|
||||||
rc->maxaura = child->valueint;
|
rc->maxaura = child->valueint;
|
||||||
|
|
|
@ -163,8 +163,7 @@ static void test_races(CuTest * tc)
|
||||||
CuAssertPtrNotNull(tc, rc);
|
CuAssertPtrNotNull(tc, rc);
|
||||||
CuAssertIntEquals(tc, RCF_NPC | RCF_WALK | RCF_UNDEAD, rc->flags);
|
CuAssertIntEquals(tc, RCF_NPC | RCF_WALK | RCF_UNDEAD, rc->flags);
|
||||||
CuAssertStrEquals(tc, "1d4", rc->def_damage);
|
CuAssertStrEquals(tc, "1d4", rc->def_damage);
|
||||||
CuAssertIntEquals(tc, 100, rc->magres);
|
CuAssertTrue(tc, frac_equal(frac_one, rc->magres));
|
||||||
CuAssertDblEquals(tc, 1.0, rc_magres(rc), 0.0);
|
|
||||||
CuAssertIntEquals(tc, 200, rc->maxaura);
|
CuAssertIntEquals(tc, 200, rc->maxaura);
|
||||||
CuAssertDblEquals(tc, 2.0, rc_maxaura(rc), 0.0);
|
CuAssertDblEquals(tc, 2.0, rc_maxaura(rc), 0.0);
|
||||||
CuAssertDblEquals(tc, 3.0, rc->regaura, 0.0);
|
CuAssertDblEquals(tc, 3.0, rc->regaura, 0.0);
|
||||||
|
|
|
@ -331,6 +331,7 @@ race *rc_create(const char *zName)
|
||||||
|
|
||||||
assert(zName);
|
assert(zName);
|
||||||
rc = (race *)calloc(sizeof(race), 1);
|
rc = (race *)calloc(sizeof(race), 1);
|
||||||
|
rc->magres.sa[1] = 1;
|
||||||
rc->hitpoints = 1;
|
rc->hitpoints = 1;
|
||||||
rc->weight = PERSON_WEIGHT;
|
rc->weight = PERSON_WEIGHT;
|
||||||
rc->capacity = 540;
|
rc->capacity = 540;
|
||||||
|
@ -383,8 +384,8 @@ bool r_insectstalled(const region * r)
|
||||||
return fval(r->terrain, ARCTIC_REGION);
|
return fval(r->terrain, ARCTIC_REGION);
|
||||||
}
|
}
|
||||||
|
|
||||||
double rc_magres(const race *rc) {
|
variant rc_magres(const race *rc) {
|
||||||
return rc->magres / 100.0;
|
return rc->magres;
|
||||||
}
|
}
|
||||||
|
|
||||||
double rc_maxaura(const race *rc) {
|
double rc_maxaura(const race *rc) {
|
||||||
|
|
|
@ -116,7 +116,7 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct race {
|
typedef struct race {
|
||||||
char *_name;
|
char *_name;
|
||||||
int magres;
|
variant magres;
|
||||||
int healing;
|
int healing;
|
||||||
int maxaura; /* Faktor auf Maximale Aura */
|
int maxaura; /* Faktor auf Maximale Aura */
|
||||||
double regaura; /* Faktor auf Regeneration */
|
double regaura; /* Faktor auf Regeneration */
|
||||||
|
@ -182,7 +182,7 @@ extern "C" {
|
||||||
|
|
||||||
int rc_luxury_trade(const struct race *rc);
|
int rc_luxury_trade(const struct race *rc);
|
||||||
int rc_herb_trade(const struct race *rc);
|
int rc_herb_trade(const struct race *rc);
|
||||||
double rc_magres(const struct race *rc);
|
variant rc_magres(const struct race *rc);
|
||||||
double rc_maxaura(const struct race *rc);
|
double rc_maxaura(const struct race *rc);
|
||||||
int rc_armor_bonus(const struct race *rc);
|
int rc_armor_bonus(const struct race *rc);
|
||||||
int rc_scare(const struct race *rc);
|
int rc_scare(const struct race *rc);
|
||||||
|
|
|
@ -24,8 +24,7 @@ static void test_rc_defaults(CuTest *tc) {
|
||||||
rc = rc_get_or_create("human");
|
rc = rc_get_or_create("human");
|
||||||
CuAssertStrEquals(tc, "human", rc->_name);
|
CuAssertStrEquals(tc, "human", rc->_name);
|
||||||
CuAssertIntEquals(tc, 0, rc_armor_bonus(rc));
|
CuAssertIntEquals(tc, 0, rc_armor_bonus(rc));
|
||||||
CuAssertIntEquals(tc, 0, rc->magres);
|
CuAssertIntEquals(tc, 0, rc->magres.sa[0]);
|
||||||
CuAssertDblEquals(tc, 0.0, rc_magres(rc), 0.0);
|
|
||||||
CuAssertIntEquals(tc, 0, rc->healing);
|
CuAssertIntEquals(tc, 0, rc->healing);
|
||||||
CuAssertDblEquals(tc, 0.0, rc_maxaura(rc), 0.0);
|
CuAssertDblEquals(tc, 0.0, rc_maxaura(rc), 0.0);
|
||||||
CuAssertDblEquals(tc, 1.0, rc->recruit_multi, 0.0);
|
CuAssertDblEquals(tc, 1.0, rc->recruit_multi, 0.0);
|
||||||
|
|
|
@ -183,35 +183,31 @@ struct rawmaterial *rm_get(region * r, const struct resource_type *rtype)
|
||||||
return rm;
|
return rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rawmaterial_type *rawmaterialtypes = 0;
|
|
||||||
|
|
||||||
struct rawmaterial_type *rmt_find(const char *str)
|
struct rawmaterial_type *rmt_find(const char *str)
|
||||||
{
|
{
|
||||||
rawmaterial_type *rmt = rawmaterialtypes;
|
resource_type *rtype = rt_find(str);
|
||||||
while (rmt && strcmp(rmt->name, str) != 0)
|
if (!rtype && strncmp(str, "rm_", 3) == 0) {
|
||||||
rmt = rmt->next;
|
rtype = rt_find(str+3);
|
||||||
return rmt;
|
}
|
||||||
|
assert(rtype);
|
||||||
|
return rtype ? rtype->raw : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rawmaterial_type *rmt_get(const struct resource_type *rtype)
|
struct rawmaterial_type *rmt_get(const struct resource_type *rtype)
|
||||||
{
|
{
|
||||||
rawmaterial_type *rmt = rawmaterialtypes;
|
return rtype->raw;
|
||||||
while (rmt && rmt->rtype != rtype)
|
|
||||||
rmt = rmt->next;
|
|
||||||
return rmt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rawmaterial_type *rmt_create(const struct resource_type *rtype,
|
struct rawmaterial_type *rmt_create(struct resource_type *rtype)
|
||||||
const char *name)
|
|
||||||
{
|
{
|
||||||
rawmaterial_type *rmtype = malloc(sizeof(rawmaterial_type));
|
rawmaterial_type *rmtype;
|
||||||
rmtype->name = strdup(name);
|
|
||||||
|
assert(!rtype->raw);
|
||||||
|
rmtype = rtype->raw = malloc(sizeof(rawmaterial_type));
|
||||||
rmtype->rtype = rtype;
|
rmtype->rtype = rtype;
|
||||||
rmtype->terraform = terraform_default;
|
rmtype->terraform = terraform_default;
|
||||||
rmtype->update = NULL;
|
rmtype->update = NULL;
|
||||||
rmtype->use = use_default;
|
rmtype->use = use_default;
|
||||||
rmtype->visible = visible_default;
|
rmtype->visible = visible_default;
|
||||||
rmtype->next = rawmaterialtypes;
|
|
||||||
rawmaterialtypes = rmtype;
|
|
||||||
return rmtype;
|
return rmtype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct building_type;
|
||||||
|
struct race;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RM_USED = 1 << 0, /* resource has been used */
|
RM_USED = 1 << 0, /* resource has been used */
|
||||||
RM_MALLORN = 1 << 1 /* this is not wood. it's mallorn */
|
RM_MALLORN = 1 << 1 /* this is not wood. it's mallorn */
|
||||||
|
@ -40,17 +43,31 @@ extern "C" {
|
||||||
struct rawmaterial *next;
|
struct rawmaterial *next;
|
||||||
} rawmaterial;
|
} 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;
|
||||||
|
const struct race *race;
|
||||||
|
unsigned int flags;
|
||||||
|
} resource_mod;
|
||||||
|
|
||||||
|
typedef struct resource_limit {
|
||||||
|
rlimit_limit limit;
|
||||||
|
rlimit_produce produce;
|
||||||
|
resource_mod *modifiers;
|
||||||
|
} resource_limit;
|
||||||
|
|
||||||
typedef struct rawmaterial_type {
|
typedef struct rawmaterial_type {
|
||||||
char *name;
|
|
||||||
const struct resource_type *rtype;
|
const struct resource_type *rtype;
|
||||||
|
|
||||||
void(*terraform) (struct rawmaterial *, const struct region *);
|
void(*terraform) (struct rawmaterial *, const struct region *);
|
||||||
void(*update) (struct rawmaterial *, const struct region *);
|
void(*update) (struct rawmaterial *, const struct region *);
|
||||||
void(*use) (struct rawmaterial *, const struct region *, int amount);
|
void(*use) (struct rawmaterial *, const struct region *, int amount);
|
||||||
int(*visible) (const struct rawmaterial *, int skilllevel);
|
int(*visible) (const struct rawmaterial *, int skilllevel);
|
||||||
|
|
||||||
/* no initialization required */
|
|
||||||
struct rawmaterial_type *next;
|
|
||||||
} rawmaterial_type;
|
} rawmaterial_type;
|
||||||
|
|
||||||
extern struct rawmaterial_type *rawmaterialtypes;
|
extern struct rawmaterial_type *rawmaterialtypes;
|
||||||
|
@ -64,8 +81,7 @@ extern "C" {
|
||||||
|
|
||||||
void add_resource(struct region *r, int level, int base, int divisor,
|
void add_resource(struct region *r, int level, int base, int divisor,
|
||||||
const struct resource_type *rtype);
|
const struct resource_type *rtype);
|
||||||
struct rawmaterial_type *rmt_create(const struct resource_type *rtype,
|
struct rawmaterial_type *rmt_create(struct resource_type *rtype);
|
||||||
const char *name);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1068,7 +1068,7 @@ void writeregion(struct gamedata *data, const region * r)
|
||||||
WRITE_INT(data->store, rhorses(r));
|
WRITE_INT(data->store, rhorses(r));
|
||||||
|
|
||||||
while (res) {
|
while (res) {
|
||||||
WRITE_TOK(data->store, res->type->name);
|
WRITE_TOK(data->store, res->type->rtype->_name);
|
||||||
WRITE_INT(data->store, res->level);
|
WRITE_INT(data->store, res->level);
|
||||||
WRITE_INT(data->store, res->amount);
|
WRITE_INT(data->store, res->amount);
|
||||||
WRITE_INT(data->store, res->startlevel);
|
WRITE_INT(data->store, res->startlevel);
|
||||||
|
@ -1529,6 +1529,11 @@ struct building *read_building(gamedata *data) {
|
||||||
READ_INT(store, &b->size);
|
READ_INT(store, &b->size);
|
||||||
READ_STR(store, name, sizeof(name));
|
READ_STR(store, name, sizeof(name));
|
||||||
b->type = bt_find(name);
|
b->type = bt_find(name);
|
||||||
|
if (!b->type) {
|
||||||
|
log_error("building %d has unknown type %s", b->no, name);
|
||||||
|
b->type = bt_find("building");
|
||||||
|
assert(b->type);
|
||||||
|
}
|
||||||
read_attribs(data, &b->attribs, b);
|
read_attribs(data, &b->attribs, b);
|
||||||
|
|
||||||
/* repairs, bug 2221: */
|
/* repairs, bug 2221: */
|
||||||
|
|
|
@ -61,6 +61,19 @@ without prior permission by the authors of Eressea.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef USE_LIBXML2
|
#ifdef USE_LIBXML2
|
||||||
|
|
||||||
|
static variant xml_fraction(xmlNodePtr node, const char *name) {
|
||||||
|
xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
|
||||||
|
if (propValue != NULL) {
|
||||||
|
int num, den = 100;
|
||||||
|
double fval = atof((const char *)propValue);
|
||||||
|
num = (int)(fval * den + 0.5);
|
||||||
|
xmlFree(propValue);
|
||||||
|
return frac_make(num, den);
|
||||||
|
}
|
||||||
|
return frac_make(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void xml_readtext(xmlNodePtr node, struct locale **lang, xmlChar ** text)
|
static void xml_readtext(xmlNodePtr node, struct locale **lang, xmlChar ** text)
|
||||||
{
|
{
|
||||||
xmlChar *propValue = xmlGetProp(node, BAD_CAST "locale");
|
xmlChar *propValue = xmlGetProp(node, BAD_CAST "locale");
|
||||||
|
@ -167,9 +180,6 @@ construction ** consPtr)
|
||||||
con->maxsize = xml_ivalue(node, "maxsize", -1);
|
con->maxsize = xml_ivalue(node, "maxsize", -1);
|
||||||
con->minskill = xml_ivalue(node, "minskill", -1);
|
con->minskill = xml_ivalue(node, "minskill", -1);
|
||||||
con->reqsize = xml_ivalue(node, "reqsize", 1);
|
con->reqsize = xml_ivalue(node, "reqsize", 1);
|
||||||
con->defense_bonus = xml_ivalue(node, "defense_bonus", 0);
|
|
||||||
con->close_combat_bonus = xml_ivalue(node, "close_combat_bonus", 0);
|
|
||||||
con->ranged_bonus = xml_ivalue(node, "ranged_bonus", 0);
|
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "building");
|
propValue = xmlGetProp(node, BAD_CAST "building");
|
||||||
if (propValue != NULL) {
|
if (propValue != NULL) {
|
||||||
|
@ -248,7 +258,7 @@ static int parse_buildings(xmlDocPtr doc)
|
||||||
btype->maxcapacity = xml_ivalue(node, "maxcapacity", btype->maxcapacity);
|
btype->maxcapacity = xml_ivalue(node, "maxcapacity", btype->maxcapacity);
|
||||||
btype->maxsize = xml_ivalue(node, "maxsize", btype->maxsize);
|
btype->maxsize = xml_ivalue(node, "maxsize", btype->maxsize);
|
||||||
|
|
||||||
btype->magres = xml_ivalue(node, "magres", btype->magres);
|
btype->magres = frac_make(xml_ivalue(node, "magres", 0), 100);
|
||||||
btype->magresbonus = xml_ivalue(node, "magresbonus", btype->magresbonus);
|
btype->magresbonus = xml_ivalue(node, "magresbonus", btype->magresbonus);
|
||||||
btype->fumblebonus = xml_ivalue(node, "fumblebonus", btype->fumblebonus);
|
btype->fumblebonus = xml_ivalue(node, "fumblebonus", btype->fumblebonus);
|
||||||
btype->auraregen = xml_fvalue(node, "auraregen", btype->auraregen);
|
btype->auraregen = xml_fvalue(node, "auraregen", btype->auraregen);
|
||||||
|
@ -301,9 +311,6 @@ static int parse_buildings(xmlDocPtr doc)
|
||||||
else if (strcmp((const char *)propValue, "age") == 0) {
|
else if (strcmp((const char *)propValue, "age") == 0) {
|
||||||
btype->age = (void(*)(struct building *))fun;
|
btype->age = (void(*)(struct building *))fun;
|
||||||
}
|
}
|
||||||
else if (strcmp((const char *)propValue, "protection") == 0) {
|
|
||||||
btype->protection = (int(*)(const struct building *, const struct unit *, building_bonus))fun;
|
|
||||||
}
|
|
||||||
else if (strcmp((const char *)propValue, "taxes") == 0) {
|
else if (strcmp((const char *)propValue, "taxes") == 0) {
|
||||||
btype->taxes = (double(*)(const struct building *, int))fun;
|
btype->taxes = (double(*)(const struct building *, int))fun;
|
||||||
}
|
}
|
||||||
|
@ -588,7 +595,7 @@ static armor_type *xml_readarmor(xmlXPathContextPtr xpath, item_type * itype)
|
||||||
unsigned int flags = ATF_NONE;
|
unsigned int flags = ATF_NONE;
|
||||||
int ac = xml_ivalue(node, "ac", 0);
|
int ac = xml_ivalue(node, "ac", 0);
|
||||||
double penalty = xml_fvalue(node, "penalty", 0.0);
|
double penalty = xml_fvalue(node, "penalty", 0.0);
|
||||||
double magres = xml_fvalue(node, "magres", 0.0);
|
variant magres = xml_fraction(node, "magres");
|
||||||
|
|
||||||
if (xml_bvalue(node, "laen", false))
|
if (xml_bvalue(node, "laen", false))
|
||||||
flags |= ATF_LAEN;
|
flags |= ATF_LAEN;
|
||||||
|
@ -613,7 +620,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
|
||||||
int offmod = xml_ivalue(node, "offmod", 0);
|
int offmod = xml_ivalue(node, "offmod", 0);
|
||||||
int defmod = xml_ivalue(node, "defmod", 0);
|
int defmod = xml_ivalue(node, "defmod", 0);
|
||||||
int reload = xml_ivalue(node, "reload", 0);
|
int reload = xml_ivalue(node, "reload", 0);
|
||||||
double magres = xml_fvalue(node, "magres", 0.0);
|
variant magres = xml_fraction(node, "magres");
|
||||||
|
|
||||||
if (xml_bvalue(node, "armorpiercing", false))
|
if (xml_bvalue(node, "armorpiercing", false))
|
||||||
flags |= WTF_ARMORPIERCING;
|
flags |= WTF_ARMORPIERCING;
|
||||||
|
@ -905,22 +912,6 @@ static int parse_rules(xmlDocPtr doc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcd(int num, int den) {
|
|
||||||
const int primes[] = { 3, 5, 7, 11, 0 };
|
|
||||||
int i=0, g = 1, p = 2;
|
|
||||||
while (p && p<=den && p<=num) {
|
|
||||||
if (num % p == 0 && den % p == 0) {
|
|
||||||
num /= p;
|
|
||||||
den /= p;
|
|
||||||
g *= p;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p = primes[i++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_resources(xmlDocPtr doc)
|
static int parse_resources(xmlDocPtr doc)
|
||||||
{
|
{
|
||||||
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
||||||
|
@ -955,12 +946,6 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
rtype->flags |= flags;
|
rtype->flags |= flags;
|
||||||
xmlFree(name);
|
xmlFree(name);
|
||||||
|
|
||||||
name = xmlGetProp(node, BAD_CAST "material");
|
|
||||||
if (name) {
|
|
||||||
rmt_create(rtype, (const char *)name);
|
|
||||||
xmlFree(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reading eressea/resources/resource/function */
|
/* reading eressea/resources/resource/function */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
|
||||||
|
@ -993,18 +978,18 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
|
if (xml_bvalue(node, "material", false)) {
|
||||||
|
rmt_create(rtype);
|
||||||
|
}
|
||||||
|
|
||||||
/* reading eressea/resources/resource/resourcelimit */
|
/* reading eressea/resources/resource/resourcelimit */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath);
|
||||||
assert(result->nodesetval->nodeNr <= 1);
|
assert(result->nodesetval->nodeNr <= 1);
|
||||||
if (result->nodesetval->nodeNr != 0) {
|
if (result->nodesetval->nodeNr != 0) {
|
||||||
resource_limit *rdata;
|
resource_limit *rdata = rtype->limit = calloc(1, sizeof(resource_limit));
|
||||||
attrib *a = a_find(rtype->attribs, &at_resourcelimit);
|
|
||||||
xmlNodePtr limit = result->nodesetval->nodeTab[0];
|
xmlNodePtr limit = result->nodesetval->nodeTab[0];
|
||||||
|
|
||||||
if (a == NULL)
|
|
||||||
a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
|
|
||||||
rdata = (resource_limit *)a->data.v;
|
|
||||||
rtype->flags |= RTF_LIMITED;
|
rtype->flags |= RTF_LIMITED;
|
||||||
xpath->node = limit;
|
xpath->node = limit;
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
@ -1041,15 +1026,7 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
rdata->modifiers[k].flags = RMF_SKILL;
|
rdata->modifiers[k].flags = RMF_SKILL;
|
||||||
}
|
}
|
||||||
else if (strcmp((const char *)propValue, "material") == 0) {
|
else if (strcmp((const char *)propValue, "material") == 0) {
|
||||||
int g, num, den = 100;
|
rdata->modifiers[k].value = xml_fraction(node, "value");
|
||||||
double fval = xml_fvalue(node, "value", 0);
|
|
||||||
/* TODO: extract into a function for reading fractions? */
|
|
||||||
num = (int)(fval * den + 0.5);
|
|
||||||
g = gcd(num, den);
|
|
||||||
num /= g;
|
|
||||||
den /= g;
|
|
||||||
rdata->modifiers[k].value.sa[0] = (short)num;
|
|
||||||
rdata->modifiers[k].value.sa[1] = (short)den;
|
|
||||||
rdata->modifiers[k].flags = RMF_SAVEMATERIAL;
|
rdata->modifiers[k].flags = RMF_SAVEMATERIAL;
|
||||||
}
|
}
|
||||||
else if (strcmp((const char *)propValue, "require") == 0) {
|
else if (strcmp((const char *)propValue, "require") == 0) {
|
||||||
|
@ -1071,7 +1048,7 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
|
|
||||||
/* reading eressea/resources/resource/resourcelimit/function */
|
/* reading eressea/resources/resource/resourcelimit/function */
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
|
||||||
if (result->nodesetval != NULL)
|
if (result->nodesetval != NULL) {
|
||||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
||||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||||
pf_generic fun;
|
pf_generic fun;
|
||||||
|
@ -1099,9 +1076,9 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
}
|
}
|
||||||
xmlFree(propValue);
|
xmlFree(propValue);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
/* reading eressea/resources/resource/resourcelimit/function */
|
/* reading eressea/resources/resource/resourcelimit/function */
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath);
|
||||||
|
@ -1129,7 +1106,6 @@ static int parse_resources(xmlDocPtr doc)
|
||||||
|
|
||||||
/* make sure old items (used in requirements) are available */
|
/* make sure old items (used in requirements) are available */
|
||||||
init_resources();
|
init_resources();
|
||||||
init_itemtypes();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1634,7 +1610,7 @@ static int parse_races(xmlDocPtr doc)
|
||||||
rc->def_damage = strdup((const char *)propValue);
|
rc->def_damage = strdup((const char *)propValue);
|
||||||
xmlFree(propValue);
|
xmlFree(propValue);
|
||||||
|
|
||||||
rc->magres = xml_ivalue(node, "magres", rc->magres);
|
rc->magres = frac_make(xml_ivalue(node, "magres", 100), 100);
|
||||||
rc->healing = (int)(xml_fvalue(node, "healing", rc->healing) * 100); /* TODO: store as int in XML */
|
rc->healing = (int)(xml_fvalue(node, "healing", rc->healing) * 100); /* TODO: store as int in XML */
|
||||||
rc->maxaura = (int)(xml_fvalue(node, "maxaura", rc->maxaura) * 100); /* TODO: store as int in XML */
|
rc->maxaura = (int)(xml_fvalue(node, "maxaura", rc->maxaura) * 100); /* TODO: store as int in XML */
|
||||||
rc->regaura = (float)xml_fvalue(node, "regaura", rc->regaura);
|
rc->regaura = (float)xml_fvalue(node, "regaura", rc->regaura);
|
||||||
|
|
|
@ -611,7 +611,7 @@ void setup_guard(guard_fixture *fix, bool armed) {
|
||||||
if (armed) {
|
if (armed) {
|
||||||
item_type *itype;
|
item_type *itype;
|
||||||
itype = it_get_or_create(rt_get_or_create("sword"));
|
itype = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2);
|
new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 2);
|
||||||
i_change(&u->items, itype, 1);
|
i_change(&u->items, itype, 1);
|
||||||
set_level(u, SK_MELEE, 2);
|
set_level(u, SK_MELEE, 2);
|
||||||
}
|
}
|
||||||
|
@ -1481,7 +1481,7 @@ static void test_armedmen(CuTest *tc) {
|
||||||
test_setup();
|
test_setup();
|
||||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
it_sword = test_create_itemtype("sword");
|
it_sword = test_create_itemtype("sword");
|
||||||
wtype = new_weapontype(it_sword, 0, 0.5, 0, 0, 0, 0, SK_MELEE, 1);
|
wtype = new_weapontype(it_sword, 0, frac_make(1, 2), 0, 0, 0, 0, SK_MELEE, 1);
|
||||||
CuAssertIntEquals(tc, 0, armedmen(u, false));
|
CuAssertIntEquals(tc, 0, armedmen(u, false));
|
||||||
CuAssertIntEquals(tc, 0, armedmen(u, true));
|
CuAssertIntEquals(tc, 0, armedmen(u, true));
|
||||||
set_level(u, SK_MELEE, 1);
|
set_level(u, SK_MELEE, 1);
|
||||||
|
|
88
src/magic.c
88
src/magic.c
|
@ -1135,27 +1135,29 @@ static int farcasting(unit * magician, region * r)
|
||||||
|
|
||||||
/* allgemeine Magieresistenz einer Einheit,
|
/* allgemeine Magieresistenz einer Einheit,
|
||||||
* reduziert magischen Schaden */
|
* reduziert magischen Schaden */
|
||||||
double magic_resistance(unit * target)
|
variant magic_resistance(unit * target)
|
||||||
{
|
{
|
||||||
attrib *a;
|
attrib *a;
|
||||||
curse *c;
|
curse *c;
|
||||||
const curse_type * ct_goodresist = 0, *ct_badresist = 0;
|
const curse_type * ct_goodresist = 0, *ct_badresist = 0;
|
||||||
const resource_type *rtype;
|
const resource_type *rtype;
|
||||||
const race *rc = u_race(target);
|
const race *rc = u_race(target);
|
||||||
double probability = rc_magres(rc);
|
variant v, prob = rc_magres(rc);
|
||||||
const plane *pl = rplane(target->region);
|
const plane *pl = rplane(target->region);
|
||||||
|
|
||||||
if (rc == get_race(RC_HIRNTOETER) && !pl) {
|
if (rc == get_race(RC_HIRNTOETER) && !pl) {
|
||||||
probability /= 2;
|
prob.sa[1] *= 2;
|
||||||
}
|
}
|
||||||
assert(target->number > 0);
|
assert(target->number > 0);
|
||||||
/* Magier haben einen Resistenzbonus vom Magietalent * 5% */
|
/* Magier haben einen Resistenzbonus vom Magietalent * 5% */
|
||||||
probability += effskill(target, SK_MAGIC, 0) * 0.05;
|
prob = frac_add(prob, frac_make(effskill(target, SK_MAGIC, 0), 20));
|
||||||
|
|
||||||
/* Auswirkungen von Zaubern auf der Einheit */
|
/* Auswirkungen von Zaubern auf der Einheit */
|
||||||
c = get_curse(target->attribs, ct_find("magicresistance"));
|
c = get_curse(target->attribs, ct_find("magicresistance"));
|
||||||
if (c) {
|
if (c) {
|
||||||
probability += 0.01 * curse_geteffect(c) * get_cursedmen(target, c);
|
/* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */
|
||||||
|
int effect = curse_geteffect_int(c) * get_cursedmen(target, c);
|
||||||
|
prob = frac_add(prob, frac_make(effect, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unicorn +10 */
|
/* Unicorn +10 */
|
||||||
|
@ -1163,7 +1165,7 @@ double magic_resistance(unit * target)
|
||||||
if (rtype) {
|
if (rtype) {
|
||||||
int n = i_get(target->items, rtype->itype);
|
int n = i_get(target->items, rtype->itype);
|
||||||
if (n) {
|
if (n) {
|
||||||
probability += n * 0.1 / target->number;
|
prob = frac_add(prob, frac_make(n, target->number * 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1180,13 +1182,15 @@ double magic_resistance(unit * target)
|
||||||
if (mage != NULL) {
|
if (mage != NULL) {
|
||||||
if (ct_goodresist && c->type == ct_goodresist) {
|
if (ct_goodresist && c->type == ct_goodresist) {
|
||||||
if (alliedunit(mage, target->faction, HELP_GUARD)) {
|
if (alliedunit(mage, target->faction, HELP_GUARD)) {
|
||||||
probability += curse_geteffect(c) * 0.01;
|
/* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */
|
||||||
|
prob = frac_add(prob, frac_make(curse_geteffect_int(c), 100));
|
||||||
ct_goodresist = 0; /* only one effect per region */
|
ct_goodresist = 0; /* only one effect per region */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ct_badresist && c->type == ct_badresist) {
|
else if (ct_badresist && c->type == ct_badresist) {
|
||||||
if (!alliedunit(mage, target->faction, HELP_GUARD)) {
|
if (!alliedunit(mage, target->faction, HELP_GUARD)) {
|
||||||
probability -= curse_geteffect(c) * 0.01;
|
/* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */
|
||||||
|
prob = frac_sub(prob, frac_make(curse_geteffect_int(c), 100));
|
||||||
ct_badresist = 0; /* only one effect per region */
|
ct_badresist = 0; /* only one effect per region */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1202,11 +1206,18 @@ double magic_resistance(unit * target)
|
||||||
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
||||||
|
|
||||||
/* gesegneter Steinkreis gibt 30% dazu */
|
/* gesegneter Steinkreis gibt 30% dazu */
|
||||||
if (btype)
|
if (btype) {
|
||||||
probability += btype->magresbonus * 0.01;
|
/* TODO: legacy. building-bonus is an integer-percentage */
|
||||||
|
prob = frac_add(prob, frac_make(btype->magresbonus, 100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (probability<0.9) ? probability : 0.9;
|
/* resistance must never be more than 90% */
|
||||||
|
v = frac_make(9, 10);
|
||||||
|
if (frac_sign(frac_sub(prob, v)) > 0) { /* prob < 90% */
|
||||||
|
return v; /* at most 90% */
|
||||||
|
}
|
||||||
|
return prob;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
@ -1223,12 +1234,12 @@ double magic_resistance(unit * target)
|
||||||
bool
|
bool
|
||||||
target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus)
|
target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus)
|
||||||
{
|
{
|
||||||
double probability = 0.0;
|
variant v02p, v98p, prob = frac_make(t_bonus, 100);
|
||||||
|
attrib *a = NULL;
|
||||||
|
|
||||||
if (magician == NULL)
|
if (magician == NULL || obj == NULL) {
|
||||||
return true;
|
|
||||||
if (obj == NULL)
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
switch (objtyp) {
|
switch (objtyp) {
|
||||||
case TYP_UNIT:
|
case TYP_UNIT:
|
||||||
|
@ -1248,43 +1259,56 @@ target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus)
|
||||||
pa = sk;
|
pa = sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Contest */
|
/* Contest, probability = 0.05 * (10 + pa - at); */
|
||||||
probability = 0.05 * (10 + pa - at);
|
prob = frac_add(prob, frac_make(10 + pa - at, 20));
|
||||||
|
prob = frac_add(prob, magic_resistance((unit *)obj));
|
||||||
probability += magic_resistance((unit *)obj);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TYP_REGION:
|
case TYP_REGION:
|
||||||
/* Bonus durch Zauber */
|
/* Bonus durch Zauber
|
||||||
probability +=
|
probability +=
|
||||||
0.01 * get_curseeffect(((region *)obj)->attribs, C_RESIST_MAGIC, 0);
|
0.01 * get_curseeffect(((region *)obj)->attribs, C_RESIST_MAGIC, 0); */
|
||||||
|
a = ((region *)obj)->attribs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYP_BUILDING:
|
case TYP_BUILDING:
|
||||||
/* Bonus durch Zauber */
|
/* Bonus durch Zauber
|
||||||
probability +=
|
probability +=
|
||||||
0.01 * get_curseeffect(((building *)obj)->attribs, C_RESIST_MAGIC, 0);
|
0.01 * get_curseeffect(((building *)obj)->attribs, C_RESIST_MAGIC, 0); */
|
||||||
|
a = ((building *)obj)->attribs;
|
||||||
/* Bonus durch Typ */
|
/* Bonus durch Typ
|
||||||
probability += 0.01 * ((building *)obj)->type->magres;
|
probability += 0.01 * ((building *)obj)->type->magres; */
|
||||||
|
prob = frac_add(prob, ((building *)obj)->type->magres);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYP_SHIP:
|
case TYP_SHIP:
|
||||||
/* Bonus durch Zauber */
|
/* Bonus durch Zauber */
|
||||||
probability +=
|
a = ((ship *)obj)->attribs;
|
||||||
0.01 * get_curseeffect(((ship *)obj)->attribs, C_RESIST_MAGIC, 0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
probability = MAX(0.02, probability + t_bonus * 0.01);
|
if (a) {
|
||||||
probability = MIN(0.98, probability);
|
const struct curse_type *ct_resist = ct_find(oldcursename(C_RESIST_MAGIC));
|
||||||
|
curse * c = get_curse(a, ct_resist);
|
||||||
|
int effect = curse_geteffect_int(c);
|
||||||
|
prob = frac_add(prob, frac_make(effect, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore results < 2% and > 98% */
|
||||||
|
v02p = frac_make(1, 50);
|
||||||
|
v98p = frac_make(49, 50);
|
||||||
|
if (frac_sign(frac_sub(prob, v02p)) < 0) {
|
||||||
|
prob = v02p;
|
||||||
|
}
|
||||||
|
else if (frac_sign(frac_sub(prob, v98p)) > 0) {
|
||||||
|
prob = v98p;
|
||||||
|
}
|
||||||
|
|
||||||
/* gibt true, wenn die Zufallszahl kleiner als die chance ist und
|
/* gibt true, wenn die Zufallszahl kleiner als die chance ist und
|
||||||
* false, wenn sie gleich oder größer ist, dh je größer die
|
* false, wenn sie gleich oder größer ist, dh je größer die
|
||||||
* Magieresistenz (chance) desto eher gibt die Funktion true zurück */
|
* Magieresistenz (chance) desto eher gibt die Funktion true zurück */
|
||||||
return chance(probability);
|
return rng_int() % prob.sa[1] < prob.sa[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
|
@ -315,7 +315,7 @@ extern "C" {
|
||||||
bool is_magic_resistant(struct unit *magician, struct unit *target, int
|
bool is_magic_resistant(struct unit *magician, struct unit *target, int
|
||||||
resist_bonus);
|
resist_bonus);
|
||||||
/* Mapperfunktion für target_resists_magic() vom Typ struct unit. */
|
/* Mapperfunktion für target_resists_magic() vom Typ struct unit. */
|
||||||
extern double magic_resistance(struct unit *target);
|
variant magic_resistance(struct unit *target);
|
||||||
/* gibt die Chance an, mit der einem Zauber widerstanden wird. Je
|
/* gibt die Chance an, mit der einem Zauber widerstanden wird. Je
|
||||||
* größer, desto resistenter ist da Opfer */
|
* größer, desto resistenter ist da Opfer */
|
||||||
bool target_resists_magic(struct unit *magician, void *obj, int objtyp,
|
bool target_resists_magic(struct unit *magician, void *obj, int objtyp,
|
||||||
|
|
|
@ -414,15 +414,15 @@ static void test_magic_resistance(CuTest *tc) {
|
||||||
test_setup();
|
test_setup();
|
||||||
rc = test_create_race("human");
|
rc = test_create_race("human");
|
||||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
||||||
CuAssertDblEquals(tc, rc->magres/100.0, magic_resistance(u), 0.01);
|
CuAssertTrue(tc, frac_equal(rc->magres, magic_resistance(u)));
|
||||||
rc->magres = 100;
|
rc->magres = frac_one;
|
||||||
CuAssertDblEquals_Msg(tc, "magic resistance is capped at 0.9", 0.9, magic_resistance(u), 0.01);
|
CuAssert(tc, "magic resistance is capped at 0.9", frac_equal(magic_resistance(u), frac_make(9, 10)));
|
||||||
rc = test_create_race("braineater");
|
rc = test_create_race("braineater");
|
||||||
rc->magres = 100;
|
rc->magres = frac_one;
|
||||||
u_setrace(u, rc);
|
u_setrace(u, rc);
|
||||||
CuAssertDblEquals_Msg(tc, "brain eaters outside astral space have 50% magres", 0.5, magic_resistance(u), 0.01);
|
CuAssert(tc, "brain eaters outside astral space have 50% magres", frac_equal(magic_resistance(u), frac_make(1, 2)));
|
||||||
u->region->_plane = get_astralplane();
|
u->region->_plane = get_astralplane();
|
||||||
CuAssertDblEquals_Msg(tc, "brain eaters in astral space have full magres", 0.9, magic_resistance(u), 0.01);
|
CuAssert(tc, "brain eaters in astral space have full magres", frac_equal(magic_resistance(u), frac_make(9, 10)));
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,32 +412,32 @@ const faction * viewer, bool see_unit)
|
||||||
if (money) {
|
if (money) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, "rm_money", money, -1);
|
report_resource(result + n, "money", money, -1);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
if (peasants) {
|
if (peasants) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, "rm_peasant", peasants, -1);
|
report_resource(result + n, "peasant", peasants, -1);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
if (horses) {
|
if (horses) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, "rm_horse", horses, -1);
|
report_resource(result + n, "horse", horses, -1);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
if (saplings) {
|
if (saplings) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, mallorn ? "rm_mallornsapling" : "rm_sapling",
|
report_resource(result + n, mallorn ? "mallornsapling" : "sapling",
|
||||||
saplings, -1);
|
saplings, -1);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
if (trees) {
|
if (trees) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, mallorn ? "rm_mallorn" : "rm_tree", trees,
|
report_resource(result + n, mallorn ? "mallorn" : "tree", trees,
|
||||||
-1);
|
-1);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@ const faction * viewer, bool see_unit)
|
||||||
if (level >= 0 && visible >= 0) {
|
if (level >= 0 && visible >= 0) {
|
||||||
if (n >= size)
|
if (n >= size)
|
||||||
return -1;
|
return -1;
|
||||||
report_resource(result + n, res->type->name, visible, level);
|
report_resource(result + n, res->type->rtype->_name, visible, level);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
res = res->next;
|
res = res->next;
|
||||||
|
|
|
@ -2851,7 +2851,8 @@ static int dc_age(struct curse *c)
|
||||||
while (*up != NULL) {
|
while (*up != NULL) {
|
||||||
unit *u = *up;
|
unit *u = *up;
|
||||||
int hp;
|
int hp;
|
||||||
double damage = c->effect * u->number;
|
variant dmg = frac_make(u->number, 1);
|
||||||
|
double damage = c->effect;
|
||||||
|
|
||||||
if (u->number <= 0 || target_resists_magic(mage, u, TYP_UNIT, 0)) {
|
if (u->number <= 0 || target_resists_magic(mage, u, TYP_UNIT, 0)) {
|
||||||
up = &u->next;
|
up = &u->next;
|
||||||
|
@ -2859,7 +2860,9 @@ static int dc_age(struct curse *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reduziert durch Magieresistenz */
|
/* Reduziert durch Magieresistenz */
|
||||||
damage *= (1.0 - magic_resistance(u));
|
dmg = frac_mul(dmg, frac_sub(frac_make(1,1), magic_resistance(u)));
|
||||||
|
damage *= dmg.sa[0];
|
||||||
|
damage /= dmg.sa[1];
|
||||||
hp = change_hitpoints(u, -(int)damage);
|
hp = change_hitpoints(u, -(int)damage);
|
||||||
|
|
||||||
ADDMSG(&u->faction->msgs, msg_message((hp>0)?"poison_damage":"poison_death", "region unit", r, u));
|
ADDMSG(&u->faction->msgs, msg_message((hp>0)?"poison_damage":"poison_death", "region unit", r, u));
|
||||||
|
|
|
@ -71,7 +71,7 @@ static void test_all_spy_message(CuTest *tc) {
|
||||||
set_factionstealth(fix.victim, fix.spy->faction);
|
set_factionstealth(fix.victim, fix.spy->faction);
|
||||||
|
|
||||||
itype = it_get_or_create(rt_get_or_create("sword"));
|
itype = it_get_or_create(rt_get_or_create("sword"));
|
||||||
new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2);
|
new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE, 2);
|
||||||
i_change(&fix.victim->items, itype, 1);
|
i_change(&fix.victim->items, itype, 1);
|
||||||
|
|
||||||
spy_message(99, fix.spy, fix.victim);
|
spy_message(99, fix.spy, fix.victim);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util/log.h>
|
#include <util/log.h>
|
||||||
|
#include <util/variant.h>
|
||||||
|
|
||||||
#pragma warning(disable: 4210)
|
#pragma warning(disable: 4210)
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ int RunAllTests(int argc, char *argv[])
|
||||||
ADD_SUITE(unicode);
|
ADD_SUITE(unicode);
|
||||||
ADD_SUITE(strings);
|
ADD_SUITE(strings);
|
||||||
ADD_SUITE(log);
|
ADD_SUITE(log);
|
||||||
|
ADD_SUITE(variant);
|
||||||
ADD_SUITE(rng);
|
ADD_SUITE(rng);
|
||||||
/* items */
|
/* items */
|
||||||
ADD_SUITE(xerewards);
|
ADD_SUITE(xerewards);
|
||||||
|
|
|
@ -230,7 +230,7 @@ building * test_create_building(region * r, const building_type * btype)
|
||||||
assert(r);
|
assert(r);
|
||||||
if (!btype) {
|
if (!btype) {
|
||||||
building_type *bt_castle = test_create_buildingtype("castle");
|
building_type *bt_castle = test_create_buildingtype("castle");
|
||||||
bt_castle->protection = building_protection;
|
bt_castle->flags |= BTF_FORTIFICATION;
|
||||||
btype = bt_castle;
|
btype = bt_castle;
|
||||||
}
|
}
|
||||||
b = new_building(btype, r, default_locale);
|
b = new_building(btype, r, default_locale);
|
||||||
|
|
|
@ -28,6 +28,7 @@ log.test.c
|
||||||
# translation.test.c
|
# translation.test.c
|
||||||
umlaut.test.c
|
umlaut.test.c
|
||||||
unicode.test.c
|
unicode.test.c
|
||||||
|
variant.test.c
|
||||||
# xml.test.c
|
# xml.test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ strings.c
|
||||||
translation.c
|
translation.c
|
||||||
umlaut.c
|
umlaut.c
|
||||||
unicode.c
|
unicode.c
|
||||||
|
variant.c
|
||||||
xml.c
|
xml.c
|
||||||
)
|
)
|
||||||
FOREACH(_FILE ${_FILES})
|
FOREACH(_FILE ${_FILES})
|
||||||
|
|
80
src/util/variant.c
Normal file
80
src/util/variant.c
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include "variant.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
const variant frac_zero = { .sa = { 0, 1 } };
|
||||||
|
const variant frac_one = { .sa = { 1, 1 } };
|
||||||
|
|
||||||
|
static int gcd(int a, int b) {
|
||||||
|
const int primes[] = { 3, 5, 7, 11, 13, 17, 19, 23, 0 };
|
||||||
|
int i = 0, g = 1, p = 2;
|
||||||
|
while (p && p <= a && p <= b) {
|
||||||
|
if (a % p == 0 && b % p == 0) {
|
||||||
|
a /= p;
|
||||||
|
b /= p;
|
||||||
|
g *= p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p = primes[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcm(int a, int b) {
|
||||||
|
int x;
|
||||||
|
if (a == b) return a;
|
||||||
|
x = (a * b);
|
||||||
|
x = (x > 0 ? x : -x) / gcd(a, b);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool frac_equal(variant a, variant b) {
|
||||||
|
return frac_sign(frac_sub(a, b)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_make(int num, int den)
|
||||||
|
{
|
||||||
|
variant v;
|
||||||
|
int g = gcd(num, den);
|
||||||
|
num /= g;
|
||||||
|
den /= g;
|
||||||
|
assert(num >= SHRT_MIN && num <= SHRT_MAX);
|
||||||
|
assert(den >= SHRT_MIN && den <= SHRT_MAX);
|
||||||
|
v.sa[0] = (short)num;
|
||||||
|
v.sa[1] = (short)den;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_add(variant a, variant b)
|
||||||
|
{
|
||||||
|
int num, den;
|
||||||
|
den = lcm(a.sa[1], b.sa[1]);
|
||||||
|
num = a.sa[0] * den / a.sa[1] + b.sa[0] * den / b.sa[1];
|
||||||
|
return frac_make(num, den);
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_sub(variant a, variant b)
|
||||||
|
{
|
||||||
|
b.sa[0] = -b.sa[0];
|
||||||
|
return frac_add(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_mul(variant a, variant b)
|
||||||
|
{
|
||||||
|
return frac_make(a.sa[0] * b.sa[0], a.sa[1] * b.sa[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
variant frac_div(variant a, variant b)
|
||||||
|
{
|
||||||
|
return frac_make(a.sa[0] * b.sa[1], a.sa[1] * b.sa[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int frac_sign(variant a) {
|
||||||
|
if (a.sa[0] == 0) return 0;
|
||||||
|
if (a.sa[0] > 0 && a.sa[1] > 0) return 1;
|
||||||
|
if (a.sa[0] < 0 && a.sa[1] < 0) return 1;
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#ifndef STRUCT_VARIANT_H
|
#ifndef STRUCT_VARIANT_H
|
||||||
#define STRUCT_VARIANT_H
|
#define STRUCT_VARIANT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +24,17 @@ extern "C" {
|
||||||
VAR_FLOAT
|
VAR_FLOAT
|
||||||
} variant_type;
|
} variant_type;
|
||||||
|
|
||||||
|
extern const variant frac_zero;
|
||||||
|
extern const variant frac_one;
|
||||||
|
|
||||||
|
variant frac_make(int num, int den);
|
||||||
|
variant frac_add(variant a, variant b);
|
||||||
|
variant frac_sub(variant a, variant b);
|
||||||
|
variant frac_mul(variant a, variant b);
|
||||||
|
variant frac_div(variant a, variant b);
|
||||||
|
int frac_sign(variant a);
|
||||||
|
bool frac_equal(variant a, variant b);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
40
src/util/variant.test.c
Normal file
40
src/util/variant.test.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include "variant.h"
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
|
||||||
|
static void test_fractions(CuTest *tc) {
|
||||||
|
variant a, b;
|
||||||
|
a = frac_make(120, 12000);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 100, a.sa[1]);
|
||||||
|
b = frac_make(23, 2300);
|
||||||
|
a = frac_add(a, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 50, a.sa[1]);
|
||||||
|
a = frac_mul(a, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 5000, a.sa[1]);
|
||||||
|
a = frac_div(b, b);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[1]);
|
||||||
|
a = frac_sub(a, a);
|
||||||
|
CuAssertIntEquals(tc, 0, a.sa[0]);
|
||||||
|
a = frac_sub(frac_one, a);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 1, a.sa[1]);
|
||||||
|
a = frac_mul(a, frac_zero);
|
||||||
|
CuAssertIntEquals(tc, 0, a.sa[0]);
|
||||||
|
CuAssertIntEquals(tc, 1, frac_sign(frac_make(-1, -1)));
|
||||||
|
CuAssertIntEquals(tc, 1, frac_sign(frac_make(1, 1)));
|
||||||
|
CuAssertIntEquals(tc, -1, frac_sign(frac_make(-1, 1)));
|
||||||
|
CuAssertIntEquals(tc, -1, frac_sign(frac_make(1, -1)));
|
||||||
|
CuAssertIntEquals(tc, 0, frac_sign(frac_make(0, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_variant_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_fractions);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -80,7 +80,6 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic)
|
||||||
int *hp, hpstack[20];
|
int *hp, hpstack[20];
|
||||||
int h;
|
int h;
|
||||||
int i, dead = 0, hp_rem = 0, heiltrank;
|
int i, dead = 0, hp_rem = 0, heiltrank;
|
||||||
double magres = magic_resistance(u);
|
|
||||||
|
|
||||||
assert(u->number);
|
assert(u->number);
|
||||||
if (fval(u_race(u), RCF_ILLUSIONARY) || u_race(u) == get_race(RC_SPELL)) {
|
if (fval(u_race(u), RCF_ILLUSIONARY) || u_race(u) == get_race(RC_SPELL)) {
|
||||||
|
@ -105,10 +104,14 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic)
|
||||||
/* Schaden */
|
/* Schaden */
|
||||||
for (i = 0; i < u->number; i++) {
|
for (i = 0; i < u->number; i++) {
|
||||||
int damage = dice_rand(dam);
|
int damage = dice_rand(dam);
|
||||||
if (magic)
|
if (magic) {
|
||||||
damage = (int)(damage * (1.0 - magres));
|
variant magres = magic_resistance(u);
|
||||||
if (physical)
|
magres = frac_sub(frac_make(1, 1), magres);
|
||||||
|
damage = damage * magres.sa[0] / magres.sa[1];
|
||||||
|
}
|
||||||
|
if (physical) {
|
||||||
damage -= nb_armor(u, i);
|
damage -= nb_armor(u, i);
|
||||||
|
}
|
||||||
hp[i] -= damage;
|
hp[i] -= damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue