forked from github/server
Merge branch 'develop' of github.com:eressea/server into develop
This commit is contained in:
commit
427c6af25d
75 changed files with 828 additions and 864 deletions
2
clibs
2
clibs
|
@ -1 +1 @@
|
|||
Subproject commit d286006a28c8aa7cd70ed7fd4cd172b50ade9727
|
||||
Subproject commit da2c0cc39b27c98ed8d31b0503426788fc236bd8
|
|
@ -25,7 +25,7 @@
|
|||
<item name="log" amount="10"/>
|
||||
<item name="stone" amount="4"/>
|
||||
</set>
|
||||
<set name="autoseed_unit">
|
||||
<set name="seed_unit">
|
||||
<item name="log" amount="50"/>
|
||||
<item name="stone" amount="50"/>
|
||||
<item name="iron" amount="50"/>
|
||||
|
@ -38,7 +38,7 @@
|
|||
<skill name="perception" level="30"/>
|
||||
<skill name="melee" level="1"/>
|
||||
</set>
|
||||
<set name="autoseed_faction">
|
||||
<set name="seed_faction">
|
||||
<item name="adamantium" amount="1"/>
|
||||
</set>
|
||||
</equipment>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<equipment>
|
||||
|
||||
<set name="seaserpent_spoils">
|
||||
<set name="spo_seaserpent">
|
||||
<item name="dragonblood" amount="2"/>
|
||||
<item name="seaserpenthead" amount="1"/>
|
||||
</set>
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
<equipment>
|
||||
|
||||
<!-- equipment given to familiars -->
|
||||
<set name="lynx_familiar">
|
||||
<set name="fam_lynx">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="tunnelworm_familiar">
|
||||
<set name="fam_tunnelworm">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="mining" level="1"/>
|
||||
<skill name="forestry" level="1"/>
|
||||
<skill name="stamina" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="eagle_familiar">
|
||||
<set name="fam_eagle">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="rat_familiar">
|
||||
<set name="fam_rat">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="stamina" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="songdragon_familiar">
|
||||
<set name="fam_songdragon">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="flee" level="2"/>
|
||||
|
@ -30,7 +30,7 @@
|
|||
<spell name="frighten" level="8"/>
|
||||
</set>
|
||||
|
||||
<set name="nymph_familiar">
|
||||
<set name="fam_nymph">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="bow" level="1"/>
|
||||
<skill name="training" level="1"/>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<spell name="appeasement" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="unicorn_familiar">
|
||||
<set name="fam_unicorn">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="resist_magic" level="3"/>
|
||||
|
@ -53,11 +53,11 @@
|
|||
<spell name="appeasement" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="direwolf_familiar">
|
||||
<set name="fam_direwolf">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="ghost_familiar">
|
||||
<set name="fam_ghost">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="steal_aura" level="6"/>
|
||||
|
@ -65,7 +65,7 @@
|
|||
<spell name="summonundead" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="imp_familiar">
|
||||
<set name="fam_imp">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="steal_aura" level="6"/>
|
||||
|
@ -73,14 +73,14 @@
|
|||
<spell name="seduction" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="dreamcat_familiar">
|
||||
<set name="fam_dreamcat">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="shapeshift" level="3"/>
|
||||
<spell name="transferauratraum" level="3"/>
|
||||
</set>
|
||||
|
||||
<set name="fairy_familiar">
|
||||
<set name="fam_fairy">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="appeasement" level="1"/>
|
||||
|
@ -88,15 +88,15 @@
|
|||
<spell name="seduction" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="owl_familiar">
|
||||
<set name="fam_owl">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="hellcat_familiar">
|
||||
<set name="fam_hellcat">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="tiger_familiar">
|
||||
<set name="fam_tiger">
|
||||
<skill name="magic" level="1"/>
|
||||
</set>
|
||||
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
<equipment>
|
||||
|
||||
<!-- one equipment-set per player-race for the first unit in a faction -->
|
||||
<set name="autoseed_dwarf">
|
||||
<set name="seed_dwarf">
|
||||
<item name="axe" amount="1"/>
|
||||
<item name="chainmail" amount="1"/>
|
||||
<skill name="melee" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_elf">
|
||||
<set name="seed_elf">
|
||||
<item name="fairyboot" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_orc">
|
||||
<set name="seed_orc">
|
||||
<skill name="polearm" level="4"/>
|
||||
<skill name="melee" level="4"/>
|
||||
<skill name="crossbow" level="4"/>
|
||||
|
@ -21,30 +21,30 @@
|
|||
<skill name="bow" level="4"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_goblin">
|
||||
<set name="seed_goblin">
|
||||
<item name="roi" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_human">
|
||||
<set name="seed_human">
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_troll">
|
||||
<set name="seed_troll">
|
||||
<skill name="building" level="1"/>
|
||||
<skill name="perception" level="3"/>
|
||||
<item name="stone" amount="50"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_demon">
|
||||
<set name="seed_demon">
|
||||
<skill name="stamina" level="15"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_insect">
|
||||
<set name="seed_insect">
|
||||
<item name="nestwarmth" amount="9"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_halfling">
|
||||
<set name="seed_halfling">
|
||||
<skill name="trade" level="1"/>
|
||||
<skill name="riding" level="2"/>
|
||||
<item name="horse" amount="2"/>
|
||||
|
@ -58,18 +58,18 @@
|
|||
<item name="incense" amount="5"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_cat">
|
||||
<set name="seed_cat">
|
||||
<item name="roi" amount="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<set name="autoseed_aquarian">
|
||||
<set name="seed_aquarian">
|
||||
<skill name="sailing" level="1"/>
|
||||
<callback name="equip_newunits"/>
|
||||
</set>
|
||||
|
||||
<!-- equipment-sets for random encounters -->
|
||||
<set name="random_desert">
|
||||
<set name="rand_desert">
|
||||
<skill name="melee" level="d2"/>
|
||||
<skill name="trade" level="d3"/>
|
||||
<skill name="riding" level="d2+1"/>
|
||||
|
@ -79,53 +79,53 @@
|
|||
<item name="money" amount="d30+19"/>
|
||||
</set>
|
||||
|
||||
<set name="random_swamp">
|
||||
<set name="rand_swamp">
|
||||
<skill name="stealth" level="d3+1"/>
|
||||
<skill name="polearm" level="d3+1"/>
|
||||
<item name="spear" amount="1"/>
|
||||
<item name="money" amount="d20+9"/>
|
||||
</set>
|
||||
|
||||
<set name="random_glacier">
|
||||
<set name="rand_glacier">
|
||||
<skill name="armorer" level="d2+1"/>
|
||||
<skill name="melee" level="d2+1"/>
|
||||
<item name="sword" amount="1"/>
|
||||
<item name="money" amount="d20+19"/>
|
||||
</set>
|
||||
|
||||
<set name="random_mountain">
|
||||
<set name="rand_mountain">
|
||||
<skill name="armorer" level="d2+1"/>
|
||||
<skill name="melee" level="d2+1"/>
|
||||
<skill name="trade" level="d3"/>
|
||||
<item name="sword" amount="1"/>
|
||||
<item name="money" amount="d40+59"/>
|
||||
<subset chance="0.6">
|
||||
<set name="item_plate"/>
|
||||
<set name="i_plate"/>
|
||||
</subset>
|
||||
</set>
|
||||
|
||||
<set name="random_highland">
|
||||
<set name="rand_highland">
|
||||
<skill name="melee" level="d2"/>
|
||||
<item name="sword" amount="1"/>
|
||||
<item name="money" amount="d10+19"/>
|
||||
</set>
|
||||
|
||||
<set name="random_forest">
|
||||
<set name="rand_forest">
|
||||
<skill name="stealth" level="d2"/>
|
||||
<skill name="perception" level="d2+1"/>
|
||||
<skill name="bow" level="d3+1"/>
|
||||
<item name="bow" amount="1"/>
|
||||
<item name="money" amount="d20+9"/>
|
||||
<subset chance="0.2">
|
||||
<set name="random_herbalist"/>
|
||||
<set name="rand_herbalist"/>
|
||||
</subset>
|
||||
</set>
|
||||
|
||||
<set name="random_herbalist">
|
||||
<set name="rand_herbalist">
|
||||
<skill name="herbalism" level="d2"/>
|
||||
</set>
|
||||
|
||||
<set name="random_villagers">
|
||||
<set name="rand_villagers">
|
||||
<item name="money" amount="d80+19"/>
|
||||
<skill name="cartmaking" level="d2-1"/>
|
||||
<skill name="mining" level="d2-1"/>
|
||||
|
@ -136,57 +136,57 @@
|
|||
<item name="money" amount="d30+10"/>
|
||||
</set>
|
||||
|
||||
<set name="random_plain">
|
||||
<set name="rand_plain">
|
||||
<item name="money" amount="d80+19"/>
|
||||
<subset>
|
||||
<set name="random_sword" chance="0.25"/>
|
||||
<set name="random_spear" chance="0.25"/>
|
||||
<set name="random_crossbow" chance="0.25"/>
|
||||
<set name="random_bow" chance="0.25"/>
|
||||
<set name="rand_sword" chance="0.25"/>
|
||||
<set name="rand_spear" chance="0.25"/>
|
||||
<set name="rand_crossbow" chance="0.25"/>
|
||||
<set name="rand_bow" chance="0.25"/>
|
||||
</subset>
|
||||
<subset chance="0.4">
|
||||
<set name="item_chain"/>
|
||||
<set name="i_chain"/>
|
||||
</subset>
|
||||
<subset chance="0.3">
|
||||
<set name="random_rider"/>
|
||||
<set name="rand_rider"/>
|
||||
</subset>
|
||||
</set>
|
||||
|
||||
<set name="random_spear">
|
||||
<set name="rand_spear">
|
||||
<skill name="polearm" level="d3"/>
|
||||
<item name="spear" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="random_sword">
|
||||
<set name="rand_sword">
|
||||
<skill name="melee" level="d3"/>
|
||||
<item name="sword" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="random_crossbow">
|
||||
<set name="rand_crossbow">
|
||||
<skill name="crossbow" level="d3"/>
|
||||
<item name="crossbow" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="random_bow">
|
||||
<set name="rand_bow">
|
||||
<skill name="bow" level="d3"/>
|
||||
<item name="bow" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="random_rider">
|
||||
<set name="rand_rider">
|
||||
<item name="horse" amount="1"/>
|
||||
<skill name="riding" level="d3"/>
|
||||
</set>
|
||||
|
||||
<set name="recruited_dracoid">
|
||||
<set name="new_dracoid">
|
||||
<!-- dracoiden, von drachen rekrutiert -->
|
||||
<skill name="polearm" level="d4+2"/>
|
||||
<skill name="melee" level="d4+2"/>
|
||||
<skill name="bow" level="d3+1"/>
|
||||
<subset>
|
||||
<!-- dracoiden haben immer eine von drei waffen -->
|
||||
<set name="item_sword" chance="0.33"/>
|
||||
<set name="item_spear" chance="0.33"/>
|
||||
<set name="item_bow" chance="0.34"/>
|
||||
<set name="i_sword" chance="0.33"/>
|
||||
<set name="i_spear" chance="0.33"/>
|
||||
<set name="i_bow" chance="0.34"/>
|
||||
</subset>
|
||||
</set>
|
||||
|
||||
|
@ -195,56 +195,52 @@
|
|||
<item name="rustysword" amount="1"/>
|
||||
<item name="rustychainmail" amount="d2-1"/>
|
||||
<subset chance="0.3">
|
||||
<set name="item_rustyshield"/>
|
||||
<set name="i_rustyshield"/>
|
||||
</subset>
|
||||
</set>
|
||||
|
||||
|
||||
<!-- single-item sets (that can be given a percentage-chance in a subset) -->
|
||||
<set name="item_plate">
|
||||
<set name="i_plate">
|
||||
<item name="plate" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_spear">
|
||||
<set name="i_spear">
|
||||
<item name="spear" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_bow">
|
||||
<set name="i_bow">
|
||||
<item name="bow" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_sword">
|
||||
<set name="i_sword">
|
||||
<item name="sword" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_chain">
|
||||
<set name="i_chain">
|
||||
<item name="chainmail" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_log">
|
||||
<item name="log" amount="1"/>
|
||||
<set name="i_rustyshield">
|
||||
<item name="rustyshield" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="item_rustychain">
|
||||
<item name="rustychainmail" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="dragon_spoils">
|
||||
<set name="spo_dragon">
|
||||
<item name="dragonblood" amount="4"/>
|
||||
<item name="dragonhead" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="youngdragon_spoils">
|
||||
<set name="spo_youngdragon">
|
||||
<item name="dragonblood" amount="1"/>
|
||||
</set>
|
||||
|
||||
<set name="wyrm_spoils">
|
||||
<set name="spo_wyrm">
|
||||
<item name="dragonblood" amount="10"/>
|
||||
<item name="dragonhead" amount="1"/>
|
||||
</set>
|
||||
|
||||
<!-- sets that are used by the monster-spawning code -->
|
||||
<set name="monster_dragon">
|
||||
<set name="seed_dragon">
|
||||
<skill name="magic" level="4"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
<skill name="stamina" level="1"/>
|
||||
|
@ -252,24 +248,24 @@
|
|||
<item name="money" amount="d500+99"/>
|
||||
</set>
|
||||
|
||||
<set name="monster_braineater">
|
||||
<set name="seed_braineater">
|
||||
<skill name="stealth" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="monster_seaserpent">
|
||||
<set name="seed_seaserpent">
|
||||
<skill name="magic" level="4"/>
|
||||
<skill name="stealth" level="2"/>
|
||||
<skill name="stamina" level="1"/>
|
||||
<skill name="perception" level="3"/>
|
||||
</set>
|
||||
|
||||
<set name="new_orc_unit">
|
||||
<set name="new_orc">
|
||||
<skill name="polearm" level="1"/>
|
||||
<skill name="melee" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="seaserpent_spoils">
|
||||
<set name="spo_seaserpent">
|
||||
<item name="dragonblood" amount="6"/>
|
||||
<item name="seaserpenthead" amount="1"/>
|
||||
</set>
|
||||
|
|
|
@ -2,26 +2,26 @@
|
|||
<equipment>
|
||||
|
||||
<!-- equipment given to familiars -->
|
||||
<set name="lynx_familiar">
|
||||
<set name="fam_lynx">
|
||||
<skill name="espionage" level="1"/>
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="tunnelworm_familiar">
|
||||
<set name="fam_tunnelworm">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="mining" level="1"/>
|
||||
<skill name="forestry" level="1"/>
|
||||
<skill name="stamina" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="eagle_familiar">
|
||||
<set name="fam_eagle">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="rat_familiar">
|
||||
<set name="fam_rat">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="espionage" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<skill name="stamina" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="songdragon_familiar">
|
||||
<set name="fam_songdragon">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="flee" level="2"/>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<spell name="frighten" level="8"/>
|
||||
</set>
|
||||
|
||||
<set name="nymph_familiar">
|
||||
<set name="fam_nymph">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="bow" level="1"/>
|
||||
<skill name="herbalism" level="1"/>
|
||||
|
@ -54,7 +54,7 @@
|
|||
<spell name="appeasement" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="unicorn_familiar">
|
||||
<set name="fam_unicorn">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
|
@ -67,12 +67,12 @@
|
|||
<spell name="appeasement" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="direwolf_familiar">
|
||||
<set name="fam_direwolf">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="ghost_familiar">
|
||||
<set name="fam_ghost">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="steal_aura" level="6"/>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<spell name="summonundead" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="imp_familiar">
|
||||
<set name="fam_imp">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="espionage" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<spell name="seduction" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="dreamcat_familiar">
|
||||
<set name="fam_dreamcat">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="espionage" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
|
@ -103,7 +103,7 @@
|
|||
<spell name="transferauratraum" level="3"/>
|
||||
</set>
|
||||
|
||||
<set name="fairy_familiar">
|
||||
<set name="fam_fairy">
|
||||
<skill name="magic" level="1"/>
|
||||
<!-- spells -->
|
||||
<spell name="appeasement" level="1"/>
|
||||
|
@ -111,19 +111,19 @@
|
|||
<spell name="seduction" level="6"/>
|
||||
</set>
|
||||
|
||||
<set name="owl_familiar">
|
||||
<set name="fam_owl">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="espionage" level="1"/>
|
||||
<skill name="stealth" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="hellcat_familiar">
|
||||
<set name="fam_hellcat">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
||||
<set name="tiger_familiar">
|
||||
<set name="fam_tiger">
|
||||
<skill name="magic" level="1"/>
|
||||
<skill name="perception" level="1"/>
|
||||
</set>
|
||||
|
|
|
@ -65,9 +65,9 @@ local function seed(r, email, race, lang)
|
|||
assert(f)
|
||||
local u = unit.create(f, r)
|
||||
assert(u)
|
||||
equip_unit(u, "autoseed_faction")
|
||||
equip_unit(u, "autoseed_unit")
|
||||
equip_unit(u, "autoseed_" .. race, 7)
|
||||
equip_unit(u, "seed_faction")
|
||||
equip_unit(u, "seed_unit")
|
||||
equip_unit(u, "seed_" .. race, 7)
|
||||
unit.create(f, r, 5):set_skill("mining", 30)
|
||||
unit.create(f, r, 5):set_skill("quarrying", 30)
|
||||
f:set_origin(r)
|
||||
|
|
|
@ -18,8 +18,9 @@ local function file_exists(name)
|
|||
if f~=nil then io.close(f) return true else return false end
|
||||
end
|
||||
|
||||
local function assert_file(filename)
|
||||
assert_equal(true, file_exists(filename))
|
||||
local function assert_file(filename, exists)
|
||||
if exists == nil then exists = true end
|
||||
assert_equal(exists, file_exists(filename))
|
||||
os.remove(filename)
|
||||
end
|
||||
|
||||
|
@ -30,9 +31,9 @@ function test_process_turn()
|
|||
assert_equal(0, write_reports())
|
||||
assert_equal(0, eressea.write_game("test.dat"))
|
||||
assert_file("data/test.dat")
|
||||
assert_file("reports/" .. get_turn() .. "-ii.nr")
|
||||
assert_file("reports/" .. get_turn() .. "-ii.cr")
|
||||
assert_file("reports/" .. get_turn() .. "-ii.txt")
|
||||
assert_file("reports/" .. get_turn() .. "-ii.nr", false)
|
||||
assert_file("reports/" .. get_turn() .. "-ii.cr", false)
|
||||
assert_file("reports/" .. get_turn() .. "-ii.txt", false)
|
||||
assert_file("reports/" .. get_turn() .. "-777.nr")
|
||||
assert_file("reports/" .. get_turn() .. "-777.cr")
|
||||
assert_file("reports/" .. get_turn() .. "-777.txt")
|
||||
|
|
|
@ -96,7 +96,7 @@ static int obs_read(struct attrib *a, void *owner, struct gamedata *data)
|
|||
{
|
||||
obs_data *od = (obs_data *)a->data.v;
|
||||
|
||||
read_reference(&od->f, data, read_faction_reference, resolve_faction);
|
||||
read_faction_reference(data, &od->f, NULL);
|
||||
READ_INT(data->store, &od->skill);
|
||||
READ_INT(data->store, &od->timer);
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -30,7 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
static int read_follow(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
read_unit_reference(data); /* skip it */
|
||||
READ_INT(data->store, NULL); /* skip it */
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,7 @@ write_hate(const attrib * a, const void *owner, struct storage *store)
|
|||
|
||||
static int read_hate(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int result = read_reference(&a->data.v, data, read_unit_reference,
|
||||
resolve_unit);
|
||||
if (result == 0 && !a->data.v) {
|
||||
if (read_unit_reference(data, (unit **)&a->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -67,8 +67,12 @@ static int keys_size(int n) {
|
|||
assert(n > 0 && n <= 4096);
|
||||
if (n <= 1) return 1;
|
||||
if (n <= 4) return 4;
|
||||
if (n <= 8) return 8;
|
||||
if (n <= 16) return 16;
|
||||
if (n <= 256) return 256;
|
||||
if (n <= 512) return 512;
|
||||
if (n <= 1024) return 1024;
|
||||
if (n <= 2048) return 2048;
|
||||
return 4096;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,9 @@ write_targetregion(const attrib * a, const void *owner, struct storage *store)
|
|||
|
||||
static int read_targetregion(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int result = read_reference(&a->data.v, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
if (result == 0 && !a->data.v)
|
||||
if (read_region_reference(data, (region **)&a->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -927,7 +927,7 @@ void kill_troop(troop dt)
|
|||
if (drops != NULL) {
|
||||
i_merge(&du->items, &drops);
|
||||
}
|
||||
sprintf(eqname, "%s_spoils", rc->_name);
|
||||
sprintf(eqname, "spo_%s", rc->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq != NULL) {
|
||||
equip_items(&du->items, eq);
|
||||
|
|
|
@ -86,8 +86,7 @@ static void lc_done(struct attrib *a)
|
|||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
lc_write(const struct attrib *a, const void *owner, struct storage *store)
|
||||
static void lc_write(const struct attrib *a, const void *owner, struct storage *store)
|
||||
{
|
||||
building_action *data = (building_action *)a->data.v;
|
||||
const char *fname = data->fname;
|
||||
|
@ -106,8 +105,7 @@ static int lc_read(struct attrib *a, void *owner, gamedata *data)
|
|||
building *b = (building *)owner;
|
||||
int result = 0;
|
||||
if (data->version < ATTRIBOWNER_VERSION) {
|
||||
result = read_reference(&b, data, read_building_reference, resolve_building);
|
||||
assert(b == owner);
|
||||
READ_INT(data->store, NULL);
|
||||
}
|
||||
READ_TOK(store, name, sizeof(name));
|
||||
if (strcmp(name, "tunnel_action") == 0) {
|
||||
|
|
|
@ -1365,8 +1365,8 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r)
|
|||
unit *u;
|
||||
int stealthmod = stealth_modifier(r->seen.mode);
|
||||
|
||||
if (r->display && r->display[0])
|
||||
fprintf(F, "\"%s\";Beschr\n", r->display);
|
||||
if (r->land && r->land->display && r->land->display[0])
|
||||
fprintf(F, "\"%s\";Beschr\n", r->land->display);
|
||||
if (fval(r->terrain, LAND_REGION)) {
|
||||
assert(r->land);
|
||||
fprintf(F, "%d;Bauern\n", rpeasants(r));
|
||||
|
|
|
@ -266,7 +266,6 @@ void add_recruits(unit * u, int number, int wanted)
|
|||
|
||||
strlcpy(equipment, "new_", sizeof(equipment));
|
||||
strlcat(equipment, u_race(u)->_name, sizeof(equipment));
|
||||
strlcat(equipment, "_unit", sizeof(equipment));
|
||||
equip_unit(unew, get_equipment(equipment));
|
||||
|
||||
if (unew != u) {
|
||||
|
|
|
@ -418,10 +418,12 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
|||
set_racename(&u2->attribs, get_racename(u->attribs));
|
||||
u_setrace(u2, u_race(u));
|
||||
u2->irace = u->irace;
|
||||
if (fval(u, UFL_HERO))
|
||||
if (fval(u, UFL_HERO)) {
|
||||
fset(u2, UFL_HERO);
|
||||
else
|
||||
}
|
||||
else {
|
||||
freset(u2, UFL_HERO);
|
||||
}
|
||||
}
|
||||
|
||||
/* Einheiten von Schiffen können nicht NACH in von
|
||||
|
|
|
@ -20,6 +20,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <util/bsdstring.h>
|
||||
#include <util/event.h>
|
||||
#include <util/functions.h>
|
||||
#include <util/gamedata.h>
|
||||
#include <util/log.h>
|
||||
#include <util/parser.h>
|
||||
#include <util/resolve.h>
|
||||
|
@ -290,10 +291,10 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
|
|||
}
|
||||
|
||||
/* compat code for old data files */
|
||||
static int caldera_read(trigger *t, struct gamedata *data)
|
||||
static int caldera_read(trigger *t, gamedata *data)
|
||||
{
|
||||
UNUSED_ARG(t);
|
||||
read_building_reference(data);
|
||||
READ_INT(data->store, NULL);
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,40 @@
|
|||
#include "region.h"
|
||||
#include "group.h"
|
||||
#include "faction.h"
|
||||
#include "objtypes.h"
|
||||
#include "plane.h"
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/gamedata.h>
|
||||
|
||||
#include <storage.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void read_allies(gamedata * data, faction *f)
|
||||
{
|
||||
ally **sfp = &f->allies;
|
||||
for (;;) {
|
||||
int aid;
|
||||
READ_INT(data->store, &aid);
|
||||
if (aid > 0) {
|
||||
ally * al = ally_add(sfp, NULL);
|
||||
int state;
|
||||
if ((al->faction = findfaction(aid)) == NULL) {
|
||||
ur_add(RESOLVE_FACTION | aid, (void **)&al->faction, NULL);
|
||||
}
|
||||
READ_INT(data->store, &state);
|
||||
al->status = state & HELP_ALL;
|
||||
sfp = &al->next;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ally * ally_find(ally *al, const struct faction *f) {
|
||||
for (; al; al = al->next) {
|
||||
if (al->faction == f) return al;
|
||||
|
|
|
@ -26,7 +26,9 @@ extern "C" {
|
|||
struct attrib_type;
|
||||
struct plane;
|
||||
struct faction;
|
||||
struct gamedata;
|
||||
struct unit;
|
||||
|
||||
extern struct attrib_type at_npcfaction;
|
||||
|
||||
typedef struct ally {
|
||||
|
@ -35,6 +37,7 @@ extern "C" {
|
|||
int status;
|
||||
} ally;
|
||||
|
||||
void read_allies(struct gamedata * data, struct faction *f);
|
||||
ally * ally_find(ally *al, const struct faction *f);
|
||||
ally * ally_add(ally **al_p, struct faction *f);
|
||||
void ally_remove(ally **al_p, struct faction *f);
|
||||
|
|
|
@ -322,25 +322,26 @@ void write_building_reference(const struct building *b, struct storage *store)
|
|||
WRITE_INT(store, (b && b->region) ? b->no : 0);
|
||||
}
|
||||
|
||||
int resolve_building(variant id, void *address)
|
||||
void resolve_building(building *b)
|
||||
{
|
||||
int result = 0;
|
||||
building *b = NULL;
|
||||
if (id.i != 0) {
|
||||
b = findbuilding(id.i);
|
||||
if (b == NULL) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
*(building **)address = b;
|
||||
return result;
|
||||
resolve(RESOLVE_BUILDING | b->no, b);
|
||||
}
|
||||
|
||||
variant read_building_reference(gamedata * data)
|
||||
int read_building_reference(gamedata * data, building **bp, resolve_fun fun)
|
||||
{
|
||||
variant result;
|
||||
READ_INT(data->store, &result.i);
|
||||
return result;
|
||||
int id;
|
||||
READ_INT(data->store, &id);
|
||||
if (id > 0) {
|
||||
*bp = findbuilding(id);
|
||||
if (*bp == NULL) {
|
||||
*bp = NULL;
|
||||
ur_add(RESOLVE_BUILDING | id, (void**)bp, fun);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*bp = NULL;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
building *new_building(const struct building_type * btype, region * r,
|
||||
|
|
|
@ -20,7 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#define H_KRNL_BUILDING
|
||||
|
||||
#include <kernel/types.h>
|
||||
#include <util/variant.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -152,10 +152,11 @@ extern "C" {
|
|||
#include "build.h"
|
||||
#define NOBUILDING NULL
|
||||
|
||||
int resolve_building(variant data, void *address);
|
||||
#define RESOLVE_BUILDING (TYP_BUILDING << 24)
|
||||
void resolve_building(building *b);
|
||||
void write_building_reference(const struct building *b,
|
||||
struct storage *store);
|
||||
variant read_building_reference(struct gamedata *data);
|
||||
int read_building_reference(struct gamedata * data, struct building **bp, resolve_fun fun);
|
||||
|
||||
struct building *findbuilding(int n);
|
||||
|
||||
|
|
|
@ -606,37 +606,26 @@ int read_borders(gamedata *data)
|
|||
{
|
||||
struct storage *store = data->store;
|
||||
for (;;) {
|
||||
int bid = 0;
|
||||
int fid, tid, bid;
|
||||
char zText[32];
|
||||
region *from, *to;
|
||||
border_type *type;
|
||||
|
||||
READ_TOK(store, zText, sizeof(zText));
|
||||
if (!strcmp(zText, "end"))
|
||||
if (!strcmp(zText, "end")) {
|
||||
break;
|
||||
}
|
||||
READ_INT(store, &bid);
|
||||
type = find_bordertype(zText);
|
||||
if (type == NULL) {
|
||||
log_error("[read_borders] connection %d type %s is not registered", bid, zText);
|
||||
assert(type || !"connection type not registered");
|
||||
}
|
||||
|
||||
READ_INT(store, &bid);
|
||||
if (data->version < UIDHASH_VERSION) {
|
||||
int fx, fy, tx, ty;
|
||||
READ_INT(store, &fx);
|
||||
READ_INT(store, &fy);
|
||||
READ_INT(store, &tx);
|
||||
READ_INT(store, &ty);
|
||||
from = findregion(fx, fy);
|
||||
to = findregion(tx, ty);
|
||||
}
|
||||
else {
|
||||
int fid, tid;
|
||||
READ_INT(store, &fid);
|
||||
READ_INT(store, &tid);
|
||||
from = findregionbyid(fid);
|
||||
to = findregionbyid(tid);
|
||||
}
|
||||
READ_INT(store, &fid);
|
||||
READ_INT(store, &tid);
|
||||
from = findregionbyid(fid);
|
||||
to = findregionbyid(tid);
|
||||
if (!to || !from) {
|
||||
log_error("%s connection %d has missing regions", zText, bid);
|
||||
if (type->read) {
|
||||
|
@ -660,19 +649,6 @@ int read_borders(gamedata *data)
|
|||
b->id = bid;
|
||||
assert(bid <= nextborder);
|
||||
type->read(b, data);
|
||||
if (data->version < NOBORDERATTRIBS_VERSION) {
|
||||
attrib *a = NULL;
|
||||
int result = read_attribs(data, &a, b);
|
||||
if (border_convert_cb) {
|
||||
border_convert_cb(b, a);
|
||||
}
|
||||
while (a) {
|
||||
a_remove(&a, a);
|
||||
}
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (!type->write) {
|
||||
log_warning("invalid border '%s' between '%s' and '%s'\n", zText, regionname(from, 0), regionname(to, 0));
|
||||
}
|
||||
|
|
|
@ -191,12 +191,7 @@ int curse_read(attrib * a, void *owner, gamedata *data)
|
|||
READ_INT(store, &c->duration);
|
||||
READ_FLT(store, &flt);
|
||||
c->vigour = flt;
|
||||
if (data->version < INTPAK_VERSION) {
|
||||
ur = resolve_unit(read_int(data->store), &c->magician);
|
||||
}
|
||||
else {
|
||||
ur = read_reference(&c->magician, data, read_unit_reference, resolve_unit);
|
||||
}
|
||||
ur = read_unit_reference(data, &c->magician, NULL);
|
||||
if (data->version < CURSEFLOAT_VERSION) {
|
||||
READ_INT(store, &n);
|
||||
c->effect = (float)n;
|
||||
|
@ -231,9 +226,7 @@ int curse_read(attrib * a, void *owner, gamedata *data)
|
|||
READ_INT(store, &c->data.i);
|
||||
}
|
||||
if (c->type->typ == CURSETYP_REGION) {
|
||||
int rr =
|
||||
read_reference(&c->data.v, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
int rr = read_region_reference(data, (region **)&c->data.v, NULL);
|
||||
if (ur == 0 && rr == 0 && !c->data.v) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* util includes */
|
||||
#include <selist.h>
|
||||
#include <critbit.h>
|
||||
#include <util/log.h>
|
||||
#include <util/rand.h>
|
||||
#include <util/rng.h>
|
||||
|
||||
|
@ -202,38 +203,85 @@ void free_ls(void *arg) {
|
|||
|
||||
static critbit_tree cb_equipments = { 0 };
|
||||
|
||||
#define EQNAMELEN 24
|
||||
|
||||
typedef struct eq_entry {
|
||||
char key[EQNAMELEN];
|
||||
equipment *value;
|
||||
} eq_entry;
|
||||
|
||||
typedef struct name_cb_data {
|
||||
const equipment *find;
|
||||
const char *result;
|
||||
} name_cb_data;
|
||||
|
||||
|
||||
static int equipment_name_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
|
||||
const eq_entry *ent = (const eq_entry *)match;
|
||||
name_cb_data *query = (name_cb_data *)cbdata;
|
||||
if (ent->value == query->find) {
|
||||
query->result = ent->key;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *equipment_name(const struct equipment *eq)
|
||||
{
|
||||
name_cb_data data;
|
||||
|
||||
data.find = eq;
|
||||
data.result = NULL;
|
||||
cb_foreach(&cb_equipments, "", 0, equipment_name_cb, &data);
|
||||
return data.result;
|
||||
}
|
||||
|
||||
equipment *get_equipment(const char *eqname)
|
||||
{
|
||||
const char *match;
|
||||
equipment *eq = NULL;
|
||||
const void *match;
|
||||
|
||||
if (strlen(eqname) >= EQNAMELEN) {
|
||||
log_warning("equipment name is longer than %d bytes: %s", EQNAMELEN - 1, eqname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
match = cb_find_str(&cb_equipments, eqname);
|
||||
if (match) {
|
||||
cb_get_kv(match, &eq, sizeof(eq));
|
||||
const eq_entry *ent = (const eq_entry *)match;
|
||||
return ent->value;
|
||||
}
|
||||
return eq;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
equipment *create_equipment(const char *eqname)
|
||||
{
|
||||
size_t len = strlen(eqname);
|
||||
eq_entry ent;
|
||||
|
||||
if (len >= EQNAMELEN) {
|
||||
log_error("equipment name is longer than %d bytes: %s", EQNAMELEN-1, eqname);
|
||||
len = EQNAMELEN-1;
|
||||
}
|
||||
memset(ent.key, 0, EQNAMELEN);
|
||||
memcpy(ent.key, eqname, len);
|
||||
|
||||
ent.value = (equipment *)calloc(1, sizeof(equipment));
|
||||
|
||||
cb_insert(&cb_equipments, &ent, sizeof(ent));
|
||||
return ent.value;
|
||||
}
|
||||
|
||||
equipment *get_or_create_equipment(const char *eqname)
|
||||
{
|
||||
equipment *eq = get_equipment(eqname);
|
||||
if (!eq) {
|
||||
size_t len;
|
||||
char data[64];
|
||||
|
||||
eq = (equipment *)calloc(1, sizeof(equipment));
|
||||
eq->name = strdup(eqname);
|
||||
|
||||
len = cb_new_kv(eqname, strlen(eqname), &eq, sizeof(eq), data);
|
||||
assert(len <= sizeof(data));
|
||||
cb_insert(&cb_equipments, data, len);
|
||||
return create_equipment(eqname);
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
|
||||
static void free_equipment(equipment *eq) {
|
||||
int i;
|
||||
free(eq->name);
|
||||
if (eq->spells) {
|
||||
selist_foreach(eq->spells, free_ls);
|
||||
selist_free(eq->spells);
|
||||
|
@ -251,10 +299,9 @@ static void free_equipment(equipment *eq) {
|
|||
}
|
||||
|
||||
static int free_equipment_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
|
||||
equipment *eq;
|
||||
cb_get_kv(match, &eq, sizeof(eq));
|
||||
free_equipment(eq);
|
||||
free(eq);
|
||||
const eq_entry * ent = (const eq_entry *)match;
|
||||
free_equipment(ent->value);
|
||||
free(ent->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ extern "C" {
|
|||
} subset;
|
||||
|
||||
typedef struct equipment {
|
||||
char *name;
|
||||
struct itemdata *items;
|
||||
char *skills[MAXSKILLS];
|
||||
struct selist *spells;
|
||||
|
@ -55,8 +54,10 @@ extern "C" {
|
|||
|
||||
void equipment_done(void);
|
||||
|
||||
const char *equipment_name(const struct equipment *eq);
|
||||
struct equipment *get_or_create_equipment(const char *eqname);
|
||||
struct equipment *get_equipment(const char *eqname);
|
||||
struct equipment *create_equipment(const char *eqname);
|
||||
|
||||
void equipment_setitem(struct equipment *eq,
|
||||
const struct item_type *itype, const char *value);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <CuTest.h>
|
||||
#include <tests.h>
|
||||
|
||||
void test_equipment(CuTest * tc)
|
||||
static void test_equipment(CuTest * tc)
|
||||
{
|
||||
equipment * eq;
|
||||
unit * u;
|
||||
|
@ -46,9 +46,33 @@ void test_equipment(CuTest * tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_get_equipment(CuTest * tc)
|
||||
{
|
||||
equipment * eq;
|
||||
|
||||
test_setup();
|
||||
eq = create_equipment("catapultammo123");
|
||||
CuAssertPtrNotNull(tc, eq);
|
||||
CuAssertStrEquals(tc, "catapultammo123", equipment_name(eq));
|
||||
eq = get_equipment("catapultammo123");
|
||||
CuAssertPtrNotNull(tc, eq);
|
||||
CuAssertStrEquals(tc, "catapultammo123", equipment_name(eq));
|
||||
eq = get_equipment("catapult");
|
||||
CuAssertPtrEquals(tc, NULL, eq);
|
||||
eq = create_equipment("catapult");
|
||||
eq = get_equipment("catapult");
|
||||
CuAssertPtrNotNull(tc, eq);
|
||||
CuAssertStrEquals(tc, "catapult", equipment_name(eq));
|
||||
eq = get_equipment("catapultammo123");
|
||||
CuAssertPtrNotNull(tc, eq);
|
||||
CuAssertStrEquals(tc, "catapultammo123", equipment_name(eq));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_equipment_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_equipment);
|
||||
SUITE_ADD_TEST(suite, test_get_equipment);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -203,21 +203,6 @@ const char *factionname(const faction * f)
|
|||
return ibuf;
|
||||
}
|
||||
|
||||
int resolve_faction(variant id, void *address)
|
||||
{
|
||||
int result = 0;
|
||||
faction *f = NULL;
|
||||
if (id.i != 0) {
|
||||
f = findfaction(id.i);
|
||||
if (f == NULL) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
assert(address);
|
||||
*(faction **)address = f;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool faction_id_is_unused(int id)
|
||||
{
|
||||
return findfaction(id) == NULL;
|
||||
|
@ -332,10 +317,25 @@ bool checkpasswd(const faction * f, const char *passwd)
|
|||
return true;
|
||||
}
|
||||
|
||||
variant read_faction_reference(gamedata * data)
|
||||
void resolve_faction(faction *f)
|
||||
{
|
||||
variant id;
|
||||
READ_INT(data->store, &id.i);
|
||||
resolve(RESOLVE_FACTION | f->no, f);
|
||||
}
|
||||
|
||||
int read_faction_reference(gamedata * data, faction **fp, resolve_fun fun)
|
||||
{
|
||||
int id;
|
||||
READ_INT(data->store, &id);
|
||||
if (id > 0) {
|
||||
*fp = findfaction(id);
|
||||
if (*fp == NULL) {
|
||||
*fp = NULL;
|
||||
ur_add(RESOLVE_FACTION | id, (void **)fp, fun);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*fp = NULL;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include "skill.h"
|
||||
#include "types.h"
|
||||
|
||||
#include <util/resolve.h>
|
||||
#include <modules/score.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -126,8 +129,10 @@ extern "C" {
|
|||
|
||||
void write_faction_reference(const struct faction *f,
|
||||
struct storage *store);
|
||||
variant read_faction_reference(struct gamedata *data);
|
||||
int resolve_faction(variant data, void *addr);
|
||||
int read_faction_reference(struct gamedata *data, struct faction **fp, resolve_fun fun);
|
||||
|
||||
#define RESOLVE_FACTION (TYP_FACTION << 24)
|
||||
void resolve_faction(struct faction *f);
|
||||
|
||||
void renumber_faction(faction * f, int no);
|
||||
void free_factions(void);
|
||||
|
|
|
@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "ally.h"
|
||||
#include "faction.h"
|
||||
#include "unit.h"
|
||||
#include "objtypes.h"
|
||||
|
||||
/* attrib includes */
|
||||
#include <attributes/raceprefix.h>
|
||||
|
@ -238,16 +239,16 @@ void read_groups(gamedata *data, faction * f)
|
|||
g = new_group(f, buf, gid);
|
||||
pa = &g->allies;
|
||||
for (;;) {
|
||||
ally *a;
|
||||
variant fid;
|
||||
|
||||
fid = read_faction_reference(data);
|
||||
if (fid.i <= 0)
|
||||
break;
|
||||
a = ally_add(pa, findfaction(fid.i));
|
||||
READ_INT(store, &a->status);
|
||||
if (!a->faction)
|
||||
ur_add(fid, &a->faction, resolve_faction);
|
||||
ally *al;
|
||||
int id;
|
||||
READ_INT(store, &id);
|
||||
if (id == 0) break;
|
||||
al = ally_add(pa, NULL);
|
||||
al->faction = findfaction(id);
|
||||
if (!al->faction) {
|
||||
ur_add(RESOLVE_FACTION | id, (void **)&al->faction, NULL);
|
||||
}
|
||||
READ_INT(store, &al->status);
|
||||
}
|
||||
read_attribs(data, &g->attribs, g);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,12 @@ static critbit_tree cb_resources;
|
|||
luxury_type *luxurytypes;
|
||||
potion_type *potiontypes;
|
||||
|
||||
#define RTYPENAMELEN 24
|
||||
typedef struct rt_entry {
|
||||
char key[RTYPENAMELEN];
|
||||
struct resource_type *value;
|
||||
} rt_entry;
|
||||
|
||||
static int res_changeaura(unit * u, const resource_type * rtype, int delta)
|
||||
{
|
||||
assert(rtype != NULL);
|
||||
|
@ -166,13 +172,19 @@ static int num_resources;
|
|||
|
||||
static void rt_register(resource_type * rtype)
|
||||
{
|
||||
char buffer[64];
|
||||
const char * name = rtype->_name;
|
||||
size_t len = strlen(name);
|
||||
rt_entry ent;
|
||||
|
||||
assert(len < sizeof(buffer) - sizeof(rtype));
|
||||
len = cb_new_kv(name, len, &rtype, sizeof(rtype), buffer);
|
||||
cb_insert(&cb_resources, buffer, len);
|
||||
if (len >= RTYPENAMELEN) {
|
||||
log_error("resource name is longer than %d bytes: %s",
|
||||
RTYPENAMELEN-1, name);
|
||||
len = RTYPENAMELEN-1;
|
||||
}
|
||||
ent.value = rtype;
|
||||
memset(ent.key, 0, RTYPENAMELEN);
|
||||
memcpy(ent.key, name, len);
|
||||
cb_insert(&cb_resources, &ent, sizeof(ent));
|
||||
++num_resources;
|
||||
}
|
||||
|
||||
|
@ -186,22 +198,11 @@ resource_type *rt_get_or_create(const char *name) {
|
|||
else {
|
||||
rtype->_name = strdup(name);
|
||||
rt_register(rtype);
|
||||
return rt_find(name);
|
||||
}
|
||||
}
|
||||
return rtype;
|
||||
}
|
||||
|
||||
static void it_register(item_type * itype)
|
||||
{
|
||||
char buffer[64];
|
||||
const char * name = itype->rtype->_name;
|
||||
size_t len = strlen(name);
|
||||
|
||||
assert(len < sizeof(buffer) - sizeof(itype));
|
||||
len = cb_new_kv(name, len, &itype, sizeof(itype), buffer);
|
||||
}
|
||||
|
||||
static const char *it_aliases[][2] = {
|
||||
{ "Runenschwert", "runesword" },
|
||||
{ "p12", "truthpotion" },
|
||||
|
@ -244,7 +245,6 @@ item_type *it_get_or_create(resource_type *rtype) {
|
|||
rtype->uchange = res_changeitem;
|
||||
rtype->itype = itype;
|
||||
rtype->flags |= RTF_ITEM;
|
||||
it_register(itype);
|
||||
return itype;
|
||||
}
|
||||
|
||||
|
@ -389,13 +389,20 @@ const potion_type *resource2potion(const resource_type * rtype)
|
|||
|
||||
resource_type *rt_find(const char *name)
|
||||
{
|
||||
void * match;
|
||||
resource_type *result = 0;
|
||||
const void *match;
|
||||
size_t len = strlen(name);
|
||||
|
||||
if (cb_find_prefix(&cb_resources, name, strlen(name) + 1, &match, 1, 0)) {
|
||||
cb_get_kv(match, &result, sizeof(result));
|
||||
if (len >= RTYPENAMELEN) {
|
||||
log_warning("resource name is longer than %d bytes: %s",
|
||||
RTYPENAMELEN-1, name);
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
match = cb_find_str(&cb_resources, name);
|
||||
if (match) {
|
||||
const rt_entry *ent = (const rt_entry *)match;
|
||||
return ent->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item **i_find(item ** i, const item_type * it)
|
||||
|
@ -792,14 +799,14 @@ int change_money(unit * u, int v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int add_resourcename_cb(const void * match, const void * key, size_t keylen, void *data)
|
||||
static int add_resourcename_cb(const void * match, const void * key,
|
||||
size_t keylen, void *data)
|
||||
{
|
||||
struct locale * lang = (struct locale *)data;
|
||||
int i = locale_index(lang);
|
||||
critbit_tree * cb = rnames + i;
|
||||
resource_type *rtype;
|
||||
resource_type *rtype = ((rt_entry *)match)->value;
|
||||
|
||||
cb_get_kv(match, &rtype, sizeof(rtype));
|
||||
for (i = 0; i != 2; ++i) {
|
||||
char buffer[128];
|
||||
const char * name = LOC(lang, resourcename(rtype, (i == 0) ? 0 : NMF_PLURAL));
|
||||
|
@ -835,20 +842,20 @@ const resource_type *findresourcetype(const char *name, const struct locale *lan
|
|||
else {
|
||||
log_debug("findresourcetype: transliterate failed for '%s'\n", name);
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
attrib_type at_showitem = {
|
||||
"showitem"
|
||||
};
|
||||
|
||||
static int add_itemname_cb(const void * match, const void * key, size_t keylen, void *data)
|
||||
static int add_itemname_cb(const void * match, const void * key,
|
||||
size_t keylen, void *data)
|
||||
{
|
||||
struct locale * lang = (struct locale *)data;
|
||||
critbit_tree * cb = inames + locale_index(lang);
|
||||
resource_type *rtype;
|
||||
resource_type *rtype = ((rt_entry *)match)->value;
|
||||
|
||||
cb_get_kv(match, &rtype, sizeof(rtype));
|
||||
if (rtype->itype) {
|
||||
int i;
|
||||
for (i = 0; i != 2; ++i) {
|
||||
|
@ -980,9 +987,10 @@ void free_rtype(resource_type *rtype) {
|
|||
free(rtype);
|
||||
}
|
||||
|
||||
int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbdata) {
|
||||
resource_type *rtype;
|
||||
cb_get_kv(match, &rtype, sizeof(rtype));
|
||||
static int free_rtype_cb(const void * match, const void * key,
|
||||
size_t keylen, void *cbdata)
|
||||
{
|
||||
resource_type *rtype = ((rt_entry *)match)->value;;
|
||||
free_rtype(rtype);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -173,12 +173,31 @@ static void test_core_resources(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_get_resource(CuTest *tc) {
|
||||
resource_type *rtype;
|
||||
|
||||
test_setup();
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, rt_find("catapultammo123"));
|
||||
rtype = rt_get_or_create("catapultammo123");
|
||||
CuAssertPtrNotNull(tc, rtype);
|
||||
CuAssertPtrEquals(tc, rtype, rt_find("catapultammo123"));
|
||||
CuAssertStrEquals(tc, "catapultammo123", rtype->_name);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, rt_find("catapult"));
|
||||
rtype = rt_get_or_create("catapult");
|
||||
CuAssertPtrEquals(tc, rtype, rt_find("catapult"));
|
||||
CuAssertStrEquals(tc, "catapult", rtype->_name);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_item_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_resourcename_no_appearance);
|
||||
SUITE_ADD_TEST(suite, test_resourcename_with_appearance);
|
||||
SUITE_ADD_TEST(suite, test_change_item);
|
||||
SUITE_ADD_TEST(suite, test_get_resource);
|
||||
SUITE_ADD_TEST(suite, test_resource_type);
|
||||
SUITE_ADD_TEST(suite, test_finditemtype);
|
||||
SUITE_ADD_TEST(suite, test_findresourcetype);
|
||||
|
|
|
@ -46,10 +46,10 @@ extern "C" {
|
|||
int level;
|
||||
} msglevel;
|
||||
|
||||
extern struct message *msg_message(const char *name, const char *sig, ...);
|
||||
extern struct message *msg_feedback(const struct unit *, struct order *cmd,
|
||||
struct message *msg_message(const char *name, const char *sig, ...);
|
||||
struct message *msg_feedback(const struct unit *, struct order *cmd,
|
||||
const char *name, const char *sig, ...);
|
||||
extern struct message *add_message(struct message_list **pm,
|
||||
struct message *add_message(struct message_list **pm,
|
||||
struct message *m);
|
||||
void addmessage(struct region *r, struct faction *f, const char *s,
|
||||
msg_t mtype, int level);
|
||||
|
|
|
@ -258,39 +258,6 @@ unsigned char index)
|
|||
return (rel + ursprung_y(f, pl, NULL) + plane_center_y(pl));
|
||||
}
|
||||
|
||||
static int resolve_plane(variant id, void *addr)
|
||||
{
|
||||
int result = 0;
|
||||
plane *pl = NULL;
|
||||
if (id.i != 0) {
|
||||
pl = getplanebyid(id.i);
|
||||
if (pl == NULL) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
*(plane **)addr = pl;
|
||||
return result;
|
||||
}
|
||||
|
||||
void write_plane_reference(const plane * u, struct storage *store)
|
||||
{
|
||||
WRITE_INT(store, u ? (u->id) : 0);
|
||||
}
|
||||
|
||||
int read_plane_reference(plane ** pp, struct storage *store)
|
||||
{
|
||||
variant id;
|
||||
READ_INT(store, &id.i);
|
||||
if (id.i == 0) {
|
||||
*pp = NULL;
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
*pp = getplanebyid(id.i);
|
||||
if (*pp == NULL)
|
||||
ur_add(id, pp, resolve_plane);
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
void free_plane(plane *pl) {
|
||||
free(pl->name);
|
||||
free(pl);
|
||||
|
|
|
@ -69,8 +69,6 @@ extern "C" {
|
|||
struct plane *get_homeplane(void);
|
||||
int rel_to_abs(const struct plane *pl, const struct faction *f,
|
||||
int rel, unsigned char index);
|
||||
void write_plane_reference(const plane * p, struct storage *store);
|
||||
int read_plane_reference(plane ** pp, struct storage *store);
|
||||
int plane_width(const plane * pl);
|
||||
int plane_height(const plane * pl);
|
||||
void adjust_coordinates(const struct faction *f, int *x, int *y, const struct plane *pl);
|
||||
|
|
|
@ -561,21 +561,15 @@ void write_race_reference(const race * rc, struct storage *store)
|
|||
WRITE_TOK(store, rc ? rc->_name : "none");
|
||||
}
|
||||
|
||||
variant read_race_reference(struct storage *store)
|
||||
struct race * read_race_reference(struct storage *store)
|
||||
{
|
||||
variant result;
|
||||
char zName[20];
|
||||
READ_TOK(store, zName, sizeof(zName));
|
||||
|
||||
if (strcmp(zName, "none") == 0) {
|
||||
result.v = NULL;
|
||||
return result;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
result.v = rc_find_i(zName);
|
||||
}
|
||||
assert(result.v != NULL);
|
||||
return result;
|
||||
return rc_find_i(zName);
|
||||
}
|
||||
|
||||
void register_race_function(race_func func, const char *name) {
|
||||
|
|
|
@ -263,7 +263,7 @@ extern "C" {
|
|||
|
||||
void write_race_reference(const struct race *rc,
|
||||
struct storage *store);
|
||||
variant read_race_reference(struct storage *store);
|
||||
struct race *read_race_reference(struct storage *store);
|
||||
|
||||
const char *raceprefix(const struct unit *u);
|
||||
void register_race_function(race_func, const char *);
|
||||
|
|
|
@ -825,8 +825,8 @@ void free_land(land_region * lr)
|
|||
lr->demands = d->next;
|
||||
free(d);
|
||||
}
|
||||
if (lr->name)
|
||||
free(lr->name);
|
||||
free(lr->name);
|
||||
free(lr->display);
|
||||
free(lr);
|
||||
}
|
||||
|
||||
|
@ -894,7 +894,6 @@ void free_region(region * r)
|
|||
{
|
||||
if (last == r)
|
||||
last = NULL;
|
||||
free(r->display);
|
||||
if (r->land)
|
||||
free_land(r->land);
|
||||
|
||||
|
@ -1088,7 +1087,6 @@ void terraform_region(region * r, const terrain_type * terrain)
|
|||
terraform_resources(r);
|
||||
|
||||
if (!fval(terrain, LAND_REGION)) {
|
||||
region_setinfo(r, NULL);
|
||||
if (r->land) {
|
||||
free_land(r->land);
|
||||
r->land = NULL;
|
||||
|
@ -1257,46 +1255,22 @@ int production(const region * r)
|
|||
return p;
|
||||
}
|
||||
|
||||
int resolve_region_coor(variant id, void *address)
|
||||
void resolve_region(region *r)
|
||||
{
|
||||
region *r = findregion(id.sa[0], id.sa[1]);
|
||||
if (r) {
|
||||
*(region **)address = r;
|
||||
return 0;
|
||||
}
|
||||
*(region **)address = NULL;
|
||||
return -1;
|
||||
resolve(RESOLVE_REGION | r->uid, r);
|
||||
}
|
||||
|
||||
int resolve_region_id(variant id, void *address)
|
||||
{
|
||||
region *r = NULL;
|
||||
if (id.i != 0) {
|
||||
r = findregionbyid(id.i);
|
||||
if (r == NULL) {
|
||||
*(region **)address = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*(region **)address = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
variant read_region_reference(gamedata *data)
|
||||
int read_region_reference(gamedata * data, region **rp, resolve_fun fun)
|
||||
{
|
||||
struct storage * store = data->store;
|
||||
variant result;
|
||||
if (data->version < UIDHASH_VERSION) {
|
||||
int n;
|
||||
READ_INT(store, &n);
|
||||
result.sa[0] = (short)n;
|
||||
READ_INT(store, &n);
|
||||
result.sa[1] = (short)n;
|
||||
int id = 0;
|
||||
|
||||
READ_INT(store, &id);
|
||||
*rp = findregionbyid(id);
|
||||
if (*rp == NULL) {
|
||||
ur_add(RESOLVE_REGION | id, (void **)rp, fun);
|
||||
}
|
||||
else {
|
||||
READ_INT(store, &result.i);
|
||||
}
|
||||
return result;
|
||||
return id;
|
||||
}
|
||||
|
||||
void write_region_reference(const region * r, struct storage *store)
|
||||
|
@ -1444,13 +1418,14 @@ faction *update_owners(region * r)
|
|||
|
||||
void region_setinfo(struct region *r, const char *info)
|
||||
{
|
||||
free(r->display);
|
||||
r->display = info ? strdup(info) : 0;
|
||||
assert(r->land);
|
||||
free(r->land->display);
|
||||
r->land->display = (info && info[0]) ? strdup(info) : 0;
|
||||
}
|
||||
|
||||
const char *region_getinfo(const region * r)
|
||||
{
|
||||
return r->display ? r->display : "";
|
||||
return (r->land && r->land->display) ? r->land->display : "";
|
||||
}
|
||||
|
||||
void region_setname(struct region *r, const char *name)
|
||||
|
|
|
@ -19,11 +19,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifndef H_KRNL_REGION
|
||||
#define H_KRNL_REGION
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <util/resolve.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "direction.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXLUXURIES 16 /* there must be no more than MAXLUXURIES kinds of luxury goods in any game */
|
||||
#define MAXREGIONS 524287 /* must be prime for hashing. 262139 was a little small */
|
||||
#define MAXTREES 100 * 1000 * 1000 /* bug 2360: some players are crazy */
|
||||
|
@ -96,7 +99,7 @@ extern "C" {
|
|||
|
||||
typedef struct land_region {
|
||||
char *name;
|
||||
/* TODO: demand kann nach Konvertierung entfernt werden. */
|
||||
char *display;
|
||||
demand *demands;
|
||||
const struct item_type *herbtype;
|
||||
short herbs;
|
||||
|
@ -122,7 +125,6 @@ extern "C" {
|
|||
int uid; /* a unique id */
|
||||
int x, y;
|
||||
struct plane *_plane; /* to access, use rplane(r) */
|
||||
char *display;
|
||||
int flags;
|
||||
unsigned short age;
|
||||
struct message_list *msgs;
|
||||
|
@ -257,11 +259,10 @@ extern "C" {
|
|||
int region_get_morale(const region * r);
|
||||
void region_set_morale(region * r, int morale, int turn);
|
||||
|
||||
#define RESOLVE_REGION (TYP_REGION << 24)
|
||||
void resolve_region(region *r);
|
||||
void write_region_reference(const struct region *r, struct storage *store);
|
||||
variant read_region_reference(struct gamedata *data);
|
||||
int resolve_region_coor(variant id, void *address);
|
||||
int resolve_region_id(variant id, void *address);
|
||||
#define RESOLVE_REGION(version) ((version<UIDHASH_VERSION)?resolve_region_coor:resolve_region_id)
|
||||
int read_region_reference(struct gamedata *data, region **rp, resolve_fun fun);
|
||||
|
||||
const char *regionname(const struct region *r, const struct faction *f);
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ race_t typus2race(unsigned char typus)
|
|||
return NORACE;
|
||||
}
|
||||
|
||||
static void read_alliances(struct gamedata *data)
|
||||
static void read_alliances(gamedata *data)
|
||||
{
|
||||
storage *store = data->store;
|
||||
char pbuf[8];
|
||||
|
@ -399,8 +399,7 @@ static void read_alliances(struct gamedata *data)
|
|||
READ_INT(store, &al->flags);
|
||||
}
|
||||
if (data->version >= ALLIANCELEADER_VERSION) {
|
||||
read_reference(&al->_leader, data, read_faction_reference,
|
||||
resolve_faction);
|
||||
read_faction_reference(data, &al->_leader, NULL);
|
||||
READ_INT(store, &id);
|
||||
}
|
||||
else {
|
||||
|
@ -420,7 +419,6 @@ void read_planes(gamedata *data) {
|
|||
READ_INT(store, &nread);
|
||||
while (--nread >= 0) {
|
||||
int id;
|
||||
variant fno;
|
||||
plane *pl;
|
||||
|
||||
READ_INT(store, &id);
|
||||
|
@ -459,9 +457,10 @@ void read_planes(gamedata *data) {
|
|||
else {
|
||||
/* WATCHERS - eliminated in February 2016, ca. turn 966 */
|
||||
if (data->version < NOWATCH_VERSION) {
|
||||
fno = read_faction_reference(data);
|
||||
while (fno.i) {
|
||||
fno = read_faction_reference(data);
|
||||
int fno;
|
||||
READ_INT(data->store, &fno);
|
||||
while (fno) {
|
||||
READ_INT(data->store, &fno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -492,7 +491,7 @@ void write_planes(storage *store) {
|
|||
}
|
||||
}
|
||||
|
||||
void write_alliances(struct gamedata *data)
|
||||
void write_alliances(gamedata *data)
|
||||
{
|
||||
alliance *al = alliances;
|
||||
while (al) {
|
||||
|
@ -509,22 +508,7 @@ void write_alliances(struct gamedata *data)
|
|||
WRITE_SECTION(data->store);
|
||||
}
|
||||
|
||||
static int resolve_owner(variant id, void *address)
|
||||
{
|
||||
region_owner *owner = (region_owner *)address;
|
||||
int result = 0;
|
||||
faction *f = NULL;
|
||||
if (id.i != 0) {
|
||||
f = findfaction(id.i);
|
||||
if (f == NULL) {
|
||||
log_error("region has an invalid owner (%s)", itoa36(id.i));
|
||||
}
|
||||
}
|
||||
owner->owner = f;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void read_owner(struct gamedata *data, region_owner ** powner)
|
||||
static void read_owner(gamedata *data, region_owner ** powner)
|
||||
{
|
||||
int since_turn;
|
||||
|
||||
|
@ -540,9 +524,7 @@ static void read_owner(struct gamedata *data, region_owner ** powner)
|
|||
owner->flags = 0;
|
||||
}
|
||||
if (data->version >= OWNER_3_VERSION) {
|
||||
int id;
|
||||
READ_INT(data->store, &id);
|
||||
owner->last_owner = id ? findfaction(id) : NULL;
|
||||
read_faction_reference(data, &owner->last_owner, NULL);
|
||||
}
|
||||
else if (data->version >= OWNER_2_VERSION) {
|
||||
int id;
|
||||
|
@ -555,7 +537,7 @@ static void read_owner(struct gamedata *data, region_owner ** powner)
|
|||
else {
|
||||
owner->last_owner = NULL;
|
||||
}
|
||||
read_reference(owner, data, &read_faction_reference, &resolve_owner);
|
||||
read_faction_reference(data, &owner->owner, NULL);
|
||||
*powner = owner;
|
||||
}
|
||||
else {
|
||||
|
@ -563,7 +545,7 @@ static void read_owner(struct gamedata *data, region_owner ** powner)
|
|||
}
|
||||
}
|
||||
|
||||
static void write_owner(struct gamedata *data, region_owner * owner)
|
||||
static void write_owner(gamedata *data, region_owner * owner)
|
||||
{
|
||||
if (owner) {
|
||||
faction *f;
|
||||
|
@ -603,8 +585,7 @@ int current_turn(void)
|
|||
return cturn;
|
||||
}
|
||||
|
||||
static void
|
||||
writeorder(struct gamedata *data, const struct order *ord,
|
||||
static void writeorder(gamedata *data, const struct order *ord,
|
||||
const struct locale *lang)
|
||||
{
|
||||
char obuf[1024];
|
||||
|
@ -613,7 +594,58 @@ writeorder(struct gamedata *data, const struct order *ord,
|
|||
WRITE_STR(data->store, obuf);
|
||||
}
|
||||
|
||||
unit *read_unit(struct gamedata *data)
|
||||
static void read_skills(gamedata *data, unit *u)
|
||||
{
|
||||
if (data->version < SKILLSORT_VERSION) {
|
||||
for (;;) {
|
||||
int n = NOSKILL, level, weeks;
|
||||
skill_t sk;
|
||||
READ_INT(data->store, &n);
|
||||
sk = (skill_t)n;
|
||||
if (sk == NOSKILL) break;
|
||||
READ_INT(data->store, &level);
|
||||
READ_INT(data->store, &weeks);
|
||||
if (level) {
|
||||
skill *sv = add_skill(u, sk);
|
||||
sv->level = sv->old = (unsigned char)level;
|
||||
sv->weeks = (unsigned char)weeks;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
READ_INT(data->store, &u->skill_size);
|
||||
u->skills = malloc(sizeof(skill)*u->skill_size);
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
int val;
|
||||
READ_INT(data->store, &val);
|
||||
sv->id = (skill_t)val;
|
||||
READ_INT(data->store, &sv->level);
|
||||
sv->old = sv->level;
|
||||
READ_INT(data->store, &sv->weeks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_skills(gamedata *data, const unit *u) {
|
||||
int i;
|
||||
skill_t sk = NOSKILL;
|
||||
WRITE_INT(data->store, u->skill_size);
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
#ifndef NDEBUG
|
||||
assert(sv->id > sk);
|
||||
sk = sv->id;
|
||||
assert(sv->weeks <= sv->level * 2 + 1);
|
||||
#endif
|
||||
WRITE_INT(data->store, sv->id);
|
||||
WRITE_INT(data->store, sv->level);
|
||||
WRITE_INT(data->store, sv->weeks);
|
||||
}
|
||||
}
|
||||
|
||||
unit *read_unit(gamedata *data)
|
||||
{
|
||||
unit *u;
|
||||
const race *rc;
|
||||
|
@ -760,20 +792,7 @@ unit *read_unit(struct gamedata *data)
|
|||
set_order(&u->thisorder, NULL);
|
||||
|
||||
assert(u_race(u));
|
||||
for (;;) {
|
||||
int n = NOSKILL, level, weeks;
|
||||
skill_t sk;
|
||||
READ_INT(data->store, &n);
|
||||
sk = (skill_t)n;
|
||||
if (sk == NOSKILL) break;
|
||||
READ_INT(data->store, &level);
|
||||
READ_INT(data->store, &weeks);
|
||||
if (level) {
|
||||
skill *sv = add_skill(u, sk);
|
||||
sv->level = sv->old = (unsigned char)level;
|
||||
sv->weeks = (unsigned char)weeks;
|
||||
}
|
||||
}
|
||||
read_skills(data, u);
|
||||
read_items(data->store, &u->items);
|
||||
READ_INT(data->store, &u->hp);
|
||||
if (u->hp < u->number) {
|
||||
|
@ -781,13 +800,14 @@ unit *read_unit(struct gamedata *data)
|
|||
u->hp = u->number;
|
||||
}
|
||||
read_attribs(data, &u->attribs, u);
|
||||
resolve_unit(u);
|
||||
return u;
|
||||
}
|
||||
|
||||
void write_unit(struct gamedata *data, const unit * u)
|
||||
void write_unit(gamedata *data, const unit * u)
|
||||
{
|
||||
order *ord;
|
||||
int i, p = 0;
|
||||
int p = 0;
|
||||
unsigned int flags = u->flags & UFL_SAVEMASK;
|
||||
const race *irace = u_irace(u);
|
||||
|
||||
|
@ -835,18 +855,7 @@ void write_unit(struct gamedata *data, const unit * u)
|
|||
WRITE_SECTION(data->store);
|
||||
|
||||
assert(u_race(u));
|
||||
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
assert(sv->weeks <= sv->level * 2 + 1);
|
||||
if (sv->level > 0) {
|
||||
WRITE_INT(data->store, sv->id);
|
||||
WRITE_INT(data->store, sv->level);
|
||||
WRITE_INT(data->store, sv->weeks);
|
||||
}
|
||||
}
|
||||
WRITE_INT(data->store, -1);
|
||||
WRITE_SECTION(data->store);
|
||||
write_skills(data, u);
|
||||
write_items(data->store, u->items);
|
||||
WRITE_SECTION(data->store);
|
||||
if (u->hp == 0 && data->version < NORCSPELL_VERSION) {
|
||||
|
@ -859,11 +868,24 @@ void write_unit(struct gamedata *data, const unit * u)
|
|||
WRITE_SECTION(data->store);
|
||||
}
|
||||
|
||||
static region *readregion(struct gamedata *data, int x, int y)
|
||||
static void read_regioninfo(gamedata *data, const region *r, char *info, size_t len) {
|
||||
if (lomem) {
|
||||
READ_STR(data->store, NULL, 0);
|
||||
}
|
||||
else {
|
||||
READ_STR(data->store, info, len);
|
||||
if (unicode_utf8_trim(info) != 0) {
|
||||
log_warning("trim region %d info to '%s'", r->uid, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static region *readregion(gamedata *data, int x, int y)
|
||||
{
|
||||
region *r = findregion(x, y);
|
||||
const terrain_type *terrain;
|
||||
char name[NAMESIZE];
|
||||
char info[DISPLAYSIZE];
|
||||
int uid = 0;
|
||||
int n;
|
||||
|
||||
|
@ -889,16 +911,11 @@ static region *readregion(struct gamedata *data, int x, int y)
|
|||
}
|
||||
r->land = 0;
|
||||
}
|
||||
if (lomem) {
|
||||
READ_STR(data->store, NULL, 0);
|
||||
if (data->version < LANDDISPLAY_VERSION) {
|
||||
read_regioninfo(data, r, info, sizeof(info));
|
||||
}
|
||||
else {
|
||||
char info[DISPLAYSIZE];
|
||||
READ_STR(data->store, info, sizeof(info));
|
||||
if (unicode_utf8_trim(info)!=0) {
|
||||
log_warning("trim region %d info to '%s'", uid, info);
|
||||
};
|
||||
region_setinfo(r, info);
|
||||
info[0] = '\0';
|
||||
}
|
||||
|
||||
READ_STR(data->store, name, sizeof(name));
|
||||
|
@ -915,15 +932,19 @@ static region *readregion(struct gamedata *data, int x, int y)
|
|||
if (fval(r->terrain, LAND_REGION)) {
|
||||
r->land = calloc(1, sizeof(land_region));
|
||||
READ_STR(data->store, name, sizeof(name));
|
||||
if (unicode_utf8_trim(name)!=0) {
|
||||
log_warning("trim region %d name to '%s'", uid, name);
|
||||
};
|
||||
if (unicode_utf8_trim(name) != 0) {
|
||||
log_warning("trim region %d name to '%s'", uid, name);
|
||||
};
|
||||
r->land->name = strdup(name);
|
||||
}
|
||||
if (r->land) {
|
||||
int i;
|
||||
rawmaterial **pres = &r->resources;
|
||||
|
||||
if (data->version >= LANDDISPLAY_VERSION) {
|
||||
read_regioninfo(data, r, info, sizeof(info));
|
||||
}
|
||||
region_setinfo(r, info);
|
||||
READ_INT(data->store, &i);
|
||||
if (i < 0) {
|
||||
log_error("number of trees in %s is %d.", regionname(r, NULL), i);
|
||||
|
@ -1001,7 +1022,11 @@ static region *readregion(struct gamedata *data, int x, int y)
|
|||
READ_INT(data->store, &n);
|
||||
rsetmoney(r, n);
|
||||
}
|
||||
|
||||
else {
|
||||
if (info[0]) {
|
||||
log_error("%s %d has a description: %s", r->terrain->_name, r->uid, info);
|
||||
}
|
||||
}
|
||||
assert(r->terrain != NULL);
|
||||
|
||||
if (r->land) {
|
||||
|
@ -1040,27 +1065,27 @@ region *read_region(gamedata *data)
|
|||
READ_INT(store, &x);
|
||||
READ_INT(store, &y);
|
||||
r = readregion(data, x, y);
|
||||
resolve_region(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void writeregion(struct gamedata *data, const region * r)
|
||||
void writeregion(gamedata *data, const region * r)
|
||||
{
|
||||
assert(r);
|
||||
assert(data);
|
||||
|
||||
WRITE_INT(data->store, r->uid);
|
||||
WRITE_STR(data->store, region_getinfo(r));
|
||||
WRITE_TOK(data->store, r->terrain->_name);
|
||||
WRITE_INT(data->store, r->flags & RF_SAVEMASK);
|
||||
WRITE_INT(data->store, r->age);
|
||||
WRITE_SECTION(data->store);
|
||||
if (fval(r->terrain, LAND_REGION)) {
|
||||
if (r->land) {
|
||||
const item_type *rht;
|
||||
struct demand *demand;
|
||||
rawmaterial *res = r->resources;
|
||||
|
||||
assert(r->land);
|
||||
WRITE_STR(data->store, (const char *)r->land->name);
|
||||
WRITE_STR(data->store, region_getinfo(r));
|
||||
assert(rtrees(r, 0) >= 0);
|
||||
assert(rtrees(r, 1) >= 0);
|
||||
assert(rtrees(r, 2) >= 0);
|
||||
|
@ -1096,11 +1121,9 @@ void writeregion(struct gamedata *data, const region * r)
|
|||
}
|
||||
WRITE_TOK(data->store, "end");
|
||||
WRITE_SECTION(data->store);
|
||||
#if RELEASE_VERSION>=REGIONOWNER_VERSION
|
||||
WRITE_INT(data->store, region_get_morale(r));
|
||||
write_owner(data, r->land->ownership);
|
||||
WRITE_SECTION(data->store);
|
||||
#endif
|
||||
}
|
||||
write_attribs(data->store, r->attribs, r);
|
||||
WRITE_SECTION(data->store);
|
||||
|
@ -1114,33 +1137,6 @@ void write_region(gamedata *data, const region *r)
|
|||
writeregion(data, r);
|
||||
}
|
||||
|
||||
static ally **addally(const faction * f, ally ** sfp, int aid, int state)
|
||||
{
|
||||
struct faction *af = findfaction(aid);
|
||||
ally *sf;
|
||||
|
||||
state &= ~HELP_OBSERVE;
|
||||
state &= ~HELP_TRAVEL;
|
||||
state &= HelpMask();
|
||||
|
||||
if (state == 0)
|
||||
return sfp;
|
||||
|
||||
while (*sfp) {
|
||||
sfp = &(*sfp)->next;
|
||||
}
|
||||
|
||||
sf = ally_add(sfp, af);
|
||||
if (!sf->faction) {
|
||||
variant id;
|
||||
id.i = aid;
|
||||
ur_add(id, &sf->faction, resolve_faction);
|
||||
}
|
||||
sf->status = state & HELP_ALL;
|
||||
|
||||
return &sf->next;
|
||||
}
|
||||
|
||||
int get_spell_level_faction(const spell * sp, void * cbdata)
|
||||
{
|
||||
static spellbook * common = 0;
|
||||
|
@ -1217,9 +1213,8 @@ void _test_write_password(gamedata *data, const faction *f) {
|
|||
write_password(data, f);
|
||||
}
|
||||
|
||||
faction *read_faction(struct gamedata * data)
|
||||
faction *read_faction(gamedata * data)
|
||||
{
|
||||
ally **sfp;
|
||||
int planes, n;
|
||||
faction *f;
|
||||
char name[DISPLAYSIZE];
|
||||
|
@ -1348,28 +1343,17 @@ faction *read_faction(struct gamedata * data)
|
|||
/* mistakes were made in the past*/
|
||||
f->options &= ~want(O_JSON);
|
||||
}
|
||||
sfp = &f->allies;
|
||||
for (;;) {
|
||||
int aid = 0;
|
||||
READ_INT(data->store, &aid);
|
||||
if (aid > 0) {
|
||||
int state;
|
||||
READ_INT(data->store, &state);
|
||||
sfp = addally(f, sfp, aid, state);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_allies(data, f);
|
||||
read_groups(data, f);
|
||||
f->spellbook = 0;
|
||||
if (data->version >= REGIONOWNER_VERSION) {
|
||||
read_spellbook(FactionSpells() ? &f->spellbook : 0, data, get_spell_level_faction, (void *)f);
|
||||
}
|
||||
resolve_faction(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
void write_faction(struct gamedata *data, const faction * f)
|
||||
void write_faction(gamedata *data, const faction * f)
|
||||
{
|
||||
ally *sf;
|
||||
ursprung *ur;
|
||||
|
@ -1450,7 +1434,7 @@ static int cb_sb_maxlevel(spellbook_entry *sbe, void *cbdata) {
|
|||
|
||||
int readgame(const char *filename)
|
||||
{
|
||||
int n;
|
||||
int n, stream_version;
|
||||
char path[MAX_PATH];
|
||||
gamedata gdata = { 0 };
|
||||
storage store;
|
||||
|
@ -1467,11 +1451,8 @@ int readgame(const char *filename)
|
|||
return -1;
|
||||
}
|
||||
sz = fread(&gdata.version, sizeof(int), 1, F);
|
||||
if (sz != sizeof(int) || gdata.version >= INTPAK_VERSION) {
|
||||
int stream_version;
|
||||
size_t sz = fread(&stream_version, sizeof(int), 1, F);
|
||||
assert((sz == 1 && stream_version == STREAM_VERSION) || !"unsupported data format");
|
||||
}
|
||||
sz = fread(&stream_version, sizeof(int), 1, F);
|
||||
assert((sz == 1 && stream_version == STREAM_VERSION) || !"unsupported data format");
|
||||
assert(gdata.version >= MIN_VERSION || !"unsupported data format");
|
||||
assert(gdata.version <= MAX_VERSION || !"unsupported data format");
|
||||
|
||||
|
@ -1540,7 +1521,8 @@ struct building *read_building(gamedata *data) {
|
|||
log_error("building too big: %s (%s size %d of %d), fixing.", buildingname(b), b->type->_name, b->size, b->type->maxsize);
|
||||
b->size = b->type->maxsize;
|
||||
}
|
||||
return b;
|
||||
resolve_building(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
void write_ship(gamedata *data, const ship *sh)
|
||||
|
@ -1558,7 +1540,7 @@ void write_ship(gamedata *data, const ship *sh)
|
|||
write_attribs(store, sh->attribs, sh);
|
||||
}
|
||||
|
||||
ship *read_ship(struct gamedata *data)
|
||||
ship *read_ship(gamedata *data)
|
||||
{
|
||||
char name[DISPLAYSIZE];
|
||||
ship *sh;
|
||||
|
@ -1725,6 +1707,9 @@ int read_game(gamedata *data)
|
|||
|
||||
/* Burgen */
|
||||
READ_INT(store, &p);
|
||||
if (p > 0 && !r->land) {
|
||||
log_error("%s, uid=%d has %d buildings", regionname(r, NULL), r->uid, p);
|
||||
}
|
||||
bp = &r->buildings;
|
||||
|
||||
while (--p >= 0) {
|
||||
|
@ -1780,10 +1765,6 @@ int read_game(gamedata *data)
|
|||
}
|
||||
read_borders(data);
|
||||
|
||||
/* Unaufgeloeste Zeiger initialisieren */
|
||||
log_debug("fixing unresolved references.");
|
||||
resolve();
|
||||
|
||||
log_debug("updating area information for lighthouses.");
|
||||
for (r = regions; r; r = r->next) {
|
||||
if (r->flags & RF_LIGHTHOUSE) {
|
||||
|
|
|
@ -116,12 +116,15 @@ static void test_readwrite_region(CuTest * tc)
|
|||
gamedata data;
|
||||
storage store;
|
||||
region *r;
|
||||
const char * lipsum = "Lorem ipsum dolor sit amet";
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, 0);
|
||||
free(r->land->name);
|
||||
r->land->name = strdup(" Hodor ");
|
||||
CuAssertStrEquals(tc, " Hodor ", r->land->name);
|
||||
region_setinfo(r, lipsum);
|
||||
CuAssertStrEquals(tc, lipsum, r->land->display);
|
||||
mstream_init(&data.strm);
|
||||
gamedata_init(&data, &store, RELEASE_VERSION);
|
||||
write_region(&data, r);
|
||||
|
@ -132,6 +135,7 @@ static void test_readwrite_region(CuTest * tc)
|
|||
r = read_region(&data);
|
||||
CuAssertPtrNotNull(tc, r);
|
||||
CuAssertStrEquals(tc, "Hodor", r->land->name);
|
||||
CuAssertStrEquals(tc, lipsum, r->land->display);
|
||||
regions = r;
|
||||
|
||||
mstream_done(&data.strm);
|
||||
|
|
|
@ -277,6 +277,10 @@ int gift_items(unit * u, int flags)
|
|||
u->items = NULL;
|
||||
break;
|
||||
}
|
||||
else if (!u3) {
|
||||
/* pick a last-chance recipient: */
|
||||
u3 = u2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (u->items && u3) {
|
||||
|
@ -644,9 +648,7 @@ void a_writesiege(const attrib * a, const void *owner, struct storage *store)
|
|||
|
||||
int a_readsiege(attrib * a, void *owner, gamedata *data)
|
||||
{
|
||||
int result = read_reference(&a->data.v, data, read_building_reference,
|
||||
resolve_building);
|
||||
if (result == 0 && !a->data.v) {
|
||||
if (read_building_reference(data, (building **)&a->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
@ -747,25 +749,26 @@ void write_unit_reference(const unit * u, struct storage *store)
|
|||
WRITE_INT(store, (u && u->region) ? u->no : 0);
|
||||
}
|
||||
|
||||
int resolve_unit(variant id, void *address)
|
||||
void resolve_unit(unit *u)
|
||||
{
|
||||
unit *u = NULL;
|
||||
if (id.i != 0) {
|
||||
u = findunit(id.i);
|
||||
if (u == NULL) {
|
||||
*(unit **)address = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*(unit **)address = u;
|
||||
return 0;
|
||||
resolve(RESOLVE_UNIT | u->no, u);
|
||||
}
|
||||
|
||||
variant read_unit_reference(gamedata *data)
|
||||
int read_unit_reference(gamedata * data, unit **up, resolve_fun fun)
|
||||
{
|
||||
variant var;
|
||||
READ_INT(data->store, &var.i);
|
||||
return var;
|
||||
int id;
|
||||
READ_INT(data->store, &id);
|
||||
if (id > 0) {
|
||||
*up = findunit(id);
|
||||
if (*up == NULL) {
|
||||
*up = NULL;
|
||||
ur_add(RESOLVE_UNIT | id, (void **)up, fun);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*up = NULL;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int get_level(const unit * u, skill_t id)
|
||||
|
@ -773,7 +776,7 @@ int get_level(const unit * u, skill_t id)
|
|||
assert(id != NOSKILL);
|
||||
if (skill_enabled(id)) {
|
||||
skill *sv = u->skills;
|
||||
while (sv != u->skills + u->skill_size) {
|
||||
while (sv != u->skills + u->skill_size && sv->id <= id) {
|
||||
if (sv->id == id) {
|
||||
return sv->level;
|
||||
}
|
||||
|
@ -795,7 +798,7 @@ void set_level(unit * u, skill_t sk, int value)
|
|||
remove_skill(u, sk);
|
||||
return;
|
||||
}
|
||||
while (sv != u->skills + u->skill_size) {
|
||||
while (sv != u->skills + u->skill_size && sv->id <= sk) {
|
||||
if (sv->id == sk) {
|
||||
sk_set(sv, value);
|
||||
return;
|
||||
|
@ -1186,35 +1189,39 @@ void set_number(unit * u, int count)
|
|||
|
||||
void remove_skill(unit * u, skill_t sk)
|
||||
{
|
||||
skill *sv = u->skills;
|
||||
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
|
||||
int i;
|
||||
skill *sv;
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
sv = u->skills + i;
|
||||
if (sv->id == sk) {
|
||||
skill *sl = u->skills + u->skill_size - 1;
|
||||
if (sl != sv) {
|
||||
*sv = *sl;
|
||||
}
|
||||
memmove(sv, sv + 1, (u->skill_size - i - 1) * sizeof(skill));
|
||||
--u->skill_size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skill *add_skill(unit * u, skill_t id)
|
||||
skill *add_skill(unit * u, skill_t sk)
|
||||
{
|
||||
skill *sv = u->skills;
|
||||
#ifndef NDEBUG
|
||||
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
|
||||
assert(sv->id != id);
|
||||
skill *sv;
|
||||
int i;
|
||||
|
||||
for (i=0; i != u->skill_size; ++i) {
|
||||
sv = u->skills+i;
|
||||
if (sv->id >= sk) break;
|
||||
}
|
||||
u->skills = realloc(u->skills, (1 + u->skill_size) * sizeof(skill));
|
||||
sv = u->skills + i;
|
||||
if (i < u->skill_size) {
|
||||
assert(sv->id != sk);
|
||||
memmove(sv + 1, sv, sizeof(skill) * (u->skill_size - i));
|
||||
}
|
||||
#endif
|
||||
++u->skill_size;
|
||||
u->skills = realloc(u->skills, u->skill_size * sizeof(skill));
|
||||
sv = (u->skills + u->skill_size - 1);
|
||||
sv->level = 0;
|
||||
sv->weeks = 1;
|
||||
sv->old = 0;
|
||||
sv->id = id;
|
||||
if (id == SK_MAGIC && u->faction && !fval(u->faction, FFL_NPC)) {
|
||||
sv->id = sk;
|
||||
if (sk == SK_MAGIC && u->faction && !fval(u->faction, FFL_NPC)) {
|
||||
assert(u->number <= 1);
|
||||
assert(max_magicians(u->faction) >= u->number);
|
||||
}
|
||||
|
@ -1224,9 +1231,10 @@ skill *add_skill(unit * u, skill_t id)
|
|||
skill *unit_skill(const unit * u, skill_t sk)
|
||||
{
|
||||
skill *sv = u->skills;
|
||||
while (sv != u->skills + u->skill_size) {
|
||||
if (sv->id == sk)
|
||||
while (sv != u->skills + u->skill_size && sv->id <= sk) {
|
||||
if (sv->id == sk) {
|
||||
return sv;
|
||||
}
|
||||
++sv;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1235,7 +1243,7 @@ skill *unit_skill(const unit * u, skill_t sk)
|
|||
bool has_skill(const unit * u, skill_t sk)
|
||||
{
|
||||
skill *sv = u->skills;
|
||||
while (sv != u->skills + u->skill_size) {
|
||||
while (sv != u->skills + u->skill_size && sv->id <= sk) {
|
||||
if (sv->id == sk) {
|
||||
return (sv->level > 0);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifndef H_KRNL_UNIT_H
|
||||
#define H_KRNL_UNIT_H
|
||||
|
||||
#include <util/variant.h>
|
||||
#include <util/resolve.h>
|
||||
#include "types.h"
|
||||
#include "skills.h"
|
||||
#include <stddef.h>
|
||||
|
@ -182,12 +182,13 @@ extern "C" {
|
|||
#define GIFT_FRIENDS 1<<1
|
||||
#define GIFT_PEASANTS 1<<2
|
||||
int gift_items(struct unit *u, int flags);
|
||||
void make_zombie(unit * u);
|
||||
void make_zombie(struct unit * u);
|
||||
|
||||
/* see resolve.h */
|
||||
int resolve_unit(variant data, void *address);
|
||||
#define RESOLVE_UNIT (TYP_UNIT << 24)
|
||||
void resolve_unit(struct unit *u);
|
||||
void write_unit_reference(const struct unit *u, struct storage *store);
|
||||
variant read_unit_reference(struct gamedata *data);
|
||||
int read_unit_reference(struct gamedata * data, struct unit **up, resolve_fun fun);
|
||||
|
||||
bool leave(struct unit *u, bool force);
|
||||
bool can_leave(struct unit *u);
|
||||
|
|
|
@ -31,7 +31,7 @@ static void test_remove_empty_units(CuTest *tc) {
|
|||
unit *u;
|
||||
int uid;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
|
@ -48,7 +48,7 @@ static void test_remove_empty_units_in_region(CuTest *tc) {
|
|||
unit *u;
|
||||
int uid;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
|
@ -69,7 +69,7 @@ static void test_remove_units_without_faction(CuTest *tc) {
|
|||
unit *u;
|
||||
int uid;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
|
@ -85,7 +85,7 @@ static void test_remove_units_with_dead_faction(CuTest *tc) {
|
|||
unit *u;
|
||||
int uid;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
|
@ -101,7 +101,7 @@ static void test_scale_number(CuTest *tc) {
|
|||
unit *u;
|
||||
const struct potion_type *ptype;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1);
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
|
@ -122,7 +122,7 @@ static void test_scale_number(CuTest *tc) {
|
|||
static void test_unit_name(CuTest *tc) {
|
||||
unit *u;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
test_create_world();
|
||||
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
|
||||
renumber_unit(u, 666);
|
||||
|
@ -334,9 +334,50 @@ static void test_inside_building(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_skills(CuTest *tc) {
|
||||
unit *u;
|
||||
skill *sv;
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
sv = add_skill(u, SK_ALCHEMY);
|
||||
CuAssertPtrNotNull(tc, sv);
|
||||
CuAssertPtrEquals(tc, sv, u->skills);
|
||||
CuAssertIntEquals(tc, 1, u->skill_size);
|
||||
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
|
||||
CuAssertIntEquals(tc, 0, sv->level);
|
||||
CuAssertIntEquals(tc, 1, sv->weeks);
|
||||
CuAssertIntEquals(tc, 0, sv->old);
|
||||
sv = add_skill(u, SK_BUILDING);
|
||||
CuAssertPtrNotNull(tc, sv);
|
||||
CuAssertIntEquals(tc, 2, u->skill_size);
|
||||
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
|
||||
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
|
||||
sv = add_skill(u, SK_LONGBOW);
|
||||
CuAssertPtrNotNull(tc, sv);
|
||||
CuAssertPtrEquals(tc, sv, unit_skill(u, SK_LONGBOW));
|
||||
CuAssertIntEquals(tc, 3, u->skill_size);
|
||||
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
|
||||
CuAssertIntEquals(tc, SK_LONGBOW, u->skills[1].id);
|
||||
CuAssertIntEquals(tc, SK_BUILDING, u->skills[2].id);
|
||||
CuAssertTrue(tc, !has_skill(u, SK_LONGBOW));
|
||||
set_level(u, SK_LONGBOW, 1);
|
||||
CuAssertTrue(tc, has_skill(u, SK_LONGBOW));
|
||||
remove_skill(u, SK_LONGBOW);
|
||||
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
|
||||
CuAssertIntEquals(tc, 2, u->skill_size);
|
||||
remove_skill(u, SK_LONGBOW);
|
||||
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
|
||||
CuAssertIntEquals(tc, 2, u->skill_size);
|
||||
remove_skill(u, SK_BUILDING);
|
||||
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
|
||||
CuAssertIntEquals(tc, 1, u->skill_size);
|
||||
CuAssertTrue(tc, !has_skill(u, SK_LONGBOW));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_limited_skills(CuTest *tc) {
|
||||
unit *u;
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
CuAssertIntEquals(tc, false, has_limited_skills(u));
|
||||
set_level(u, SK_ENTERTAINMENT, 1);
|
||||
|
@ -592,6 +633,7 @@ CuSuite *get_unit_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_skill_familiar);
|
||||
SUITE_ADD_TEST(suite, test_age_familiar);
|
||||
SUITE_ADD_TEST(suite, test_inside_building);
|
||||
SUITE_ADD_TEST(suite, test_skills);
|
||||
SUITE_ADD_TEST(suite, test_limited_skills);
|
||||
SUITE_ADD_TEST(suite, test_renumber_unit);
|
||||
SUITE_ADD_TEST(suite, test_name_unit);
|
||||
|
|
|
@ -960,7 +960,7 @@ static void add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
|
|||
equipment_addspell(eq, name, level);
|
||||
}
|
||||
else {
|
||||
log_error("spell '%s' for equipment-set '%s' has no level\n", name, eq->name);
|
||||
log_error("spell '%s' for equipment-set '%s' has no level\n", name, equipment_name(eq));
|
||||
}
|
||||
xmlFree(propValue);
|
||||
}
|
||||
|
@ -980,7 +980,7 @@ static void add_skills(equipment * eq, xmlNodeSetPtr nsetSkills)
|
|||
assert(propValue != NULL);
|
||||
sk = findskill((const char *)propValue);
|
||||
if (sk == NOSKILL) {
|
||||
log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, eq->name);
|
||||
log_error("unknown skill '%s' in equipment-set %s\n", (const char *)propValue, equipment_name(eq));
|
||||
xmlFree(propValue);
|
||||
}
|
||||
else {
|
||||
|
@ -1044,7 +1044,7 @@ add_subsets(xmlDocPtr doc, equipment * eq, xmlNodeSetPtr nsetSubsets)
|
|||
}
|
||||
}
|
||||
if (totalChance > 1.0f) {
|
||||
log_error("total chance exceeds 1.0: %f in equipment set %s.\n", totalChance, eq->name);
|
||||
log_error("total chance exceeds 1.0: %f in equipment set %s.\n", totalChance, equipment_name(eq));
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
|
@ -1069,9 +1069,13 @@ static int parse_equipment(xmlDocPtr doc)
|
|||
xmlChar *propName = xmlGetProp(node, BAD_CAST "name");
|
||||
|
||||
if (propName != NULL) {
|
||||
equipment *eq = get_or_create_equipment((const char *)propName);
|
||||
equipment *eq = get_equipment((const char *)propName);
|
||||
xmlXPathObjectPtr xpathResult;
|
||||
|
||||
if (!eq) {
|
||||
eq = create_equipment((const char *)propName);
|
||||
}
|
||||
|
||||
xpath->node = node;
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "callback", xpath);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <kernel/config.h>
|
||||
#include "keyword.h"
|
||||
|
||||
#include <util/bsdstring.h>
|
||||
#include <util/language.h>
|
||||
#include <util/umlaut.h>
|
||||
#include <util/log.h>
|
||||
|
@ -20,7 +21,7 @@ const char * keyword(keyword_t kwd)
|
|||
if (!result[0]) {
|
||||
strcpy(result, "keyword::");
|
||||
}
|
||||
strcpy(result + 9, keywords[kwd]);
|
||||
strlcpy(result + 9, keywords[kwd], sizeof(result) - 9);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1559,11 +1559,11 @@ int display_cmd(unit * u, struct order *ord)
|
|||
break;
|
||||
|
||||
case P_REGION:
|
||||
if (u->faction != region_get_owner(r)) {
|
||||
if (!r->land || u->faction != region_get_owner(r)) {
|
||||
cmistake(u, ord, 147, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
s = &r->display;
|
||||
s = &r->land->display;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -227,7 +227,7 @@ static void test_display_cmd(CuTest *tc) {
|
|||
|
||||
ord = create_order(K_DISPLAY, f->locale, "%s Hodor", LOC(f->locale, parameters[P_REGION]));
|
||||
CuAssertIntEquals(tc, 0, display_cmd(u, ord));
|
||||
CuAssertPtrEquals(tc, NULL, r->display);
|
||||
CuAssertPtrEquals(tc, NULL, r->land->display);
|
||||
free_order(ord);
|
||||
|
||||
test_cleanup();
|
||||
|
|
92
src/magic.c
92
src/magic.c
|
@ -356,9 +356,7 @@ static int read_seenspell(attrib * a, void *owner, struct gamedata *data)
|
|||
}
|
||||
sp = find_spell(token);
|
||||
if (!sp) {
|
||||
log_warning("read_seenspell: could not find spell '%s'\n", token);
|
||||
}
|
||||
if (!sp) {
|
||||
log_info("read_seenspell: could not find spell '%s'\n", token);
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
a->data.v = sp;
|
||||
|
@ -2264,26 +2262,21 @@ bool create_newfamiliar(unit * mage, unit * familiar)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int resolve_familiar(variant data, void *addr)
|
||||
{
|
||||
unit *familiar;
|
||||
int result = resolve_unit(data, &familiar);
|
||||
if (result == 0 && familiar) {
|
||||
static void * resolve_familiar(int id, void *data) {
|
||||
if (data) {
|
||||
unit *familiar = (unit *)data;
|
||||
attrib *a = a_find(familiar->attribs, &at_familiarmage);
|
||||
if (a != NULL && a->data.v) {
|
||||
unit *mage = (unit *)a->data.v;
|
||||
set_familiar(mage, familiar);
|
||||
}
|
||||
}
|
||||
*(unit **)addr = familiar;
|
||||
return result;
|
||||
return data;
|
||||
}
|
||||
|
||||
static int read_familiar(attrib * a, void *owner, struct gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&a->data.v, data, read_unit_reference, resolve_familiar);
|
||||
if (result == 0 && a->data.v == NULL) {
|
||||
if (read_unit_reference(data, (unit **)&a->data.v, resolve_familiar) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
@ -2348,52 +2341,42 @@ unit *has_clone(unit * mage)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int resolve_clone(variant data, void *addr)
|
||||
{
|
||||
unit *clone;
|
||||
int result = resolve_unit(data, &clone);
|
||||
if (result == 0 && clone) {
|
||||
static void * resolve_clone(int id, void *data) {
|
||||
if (data) {
|
||||
unit *clone = (unit *)data;
|
||||
attrib *a = a_find(clone->attribs, &at_clonemage);
|
||||
if (a != NULL && a->data.v) {
|
||||
unit *mage = (unit *)a->data.v;
|
||||
set_clone(mage, clone);
|
||||
}
|
||||
}
|
||||
*(unit **)addr = clone;
|
||||
return result;
|
||||
return data;
|
||||
}
|
||||
|
||||
static int read_clone(attrib * a, void *owner, struct gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&a->data.v, data, read_unit_reference, resolve_clone);
|
||||
if (result == 0 && a->data.v == NULL) {
|
||||
if (read_unit_reference(data, (unit **)&a->data.v, resolve_clone) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
/* mages */
|
||||
static int resolve_mage(variant data, void *addr)
|
||||
{
|
||||
unit *mage;
|
||||
int result = resolve_unit(data, &mage);
|
||||
if (result == 0 && mage) {
|
||||
static void * resolve_mage(int id, void *data) {
|
||||
if (data) {
|
||||
unit *mage = (unit *)data;
|
||||
attrib *a = a_find(mage->attribs, &at_familiar);
|
||||
if (a != NULL && a->data.v) {
|
||||
unit *familiar = (unit *)a->data.v;
|
||||
set_familiar(mage, familiar);
|
||||
}
|
||||
}
|
||||
*(unit **)addr = mage;
|
||||
return result;
|
||||
return data;
|
||||
}
|
||||
|
||||
static int read_magician(attrib * a, void *owner, struct gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&a->data.v, data, read_unit_reference, resolve_mage);
|
||||
if (result == 0 && a->data.v == NULL) {
|
||||
if (read_unit_reference(data, (unit **)&a->data.v, resolve_mage) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
@ -3009,30 +2992,36 @@ int cast_spell(struct castorder *co)
|
|||
|
||||
static critbit_tree cb_spellbooks;
|
||||
|
||||
#define SBNAMELEN 16
|
||||
|
||||
typedef struct sb_entry {
|
||||
char key[SBNAMELEN];
|
||||
spellbook *value;
|
||||
} sb_entry;
|
||||
|
||||
spellbook * get_spellbook(const char * name)
|
||||
{
|
||||
char buffer[64];
|
||||
spellbook * result;
|
||||
void * match;
|
||||
size_t len = strlen(name);
|
||||
const void * match;
|
||||
|
||||
if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0) > 0) {
|
||||
cb_get_kv(match, &result, sizeof(result));
|
||||
if (len >= SBNAMELEN) {
|
||||
log_error("spellbook name is longer than %d bytes: %s", SBNAMELEN-1, name);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
size_t len = strlen(name);
|
||||
result = create_spellbook(name);
|
||||
assert(strlen(name) + sizeof(result) < sizeof(buffer));
|
||||
len = cb_new_kv(name, len, &result, sizeof(result), buffer);
|
||||
if (cb_insert(&cb_spellbooks, buffer, len) == CB_EXISTS) {
|
||||
|
||||
match = cb_find_str(&cb_spellbooks, name);
|
||||
if (!match) {
|
||||
sb_entry ent;
|
||||
memset(ent.key, 0, SBNAMELEN);
|
||||
memcpy(ent.key, name, len);
|
||||
ent.value = create_spellbook(name);
|
||||
if (cb_insert(&cb_spellbooks, &ent, sizeof(ent)) == CB_EXISTS) {
|
||||
log_error("cb_insert failed although cb_find returned nothing for spellbook=%s", name);
|
||||
assert(!"should not happen");
|
||||
}
|
||||
result = 0;
|
||||
if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0) > 0) {
|
||||
cb_get_kv(match, &result, sizeof(result));
|
||||
}
|
||||
return ent.value;
|
||||
}
|
||||
return result;
|
||||
return ((const sb_entry *)match)->value;
|
||||
}
|
||||
|
||||
void free_spellbook(spellbook *sb) {
|
||||
|
@ -3041,9 +3030,8 @@ void free_spellbook(spellbook *sb) {
|
|||
}
|
||||
|
||||
static int free_spellbook_cb(const void *match, const void *key, size_t keylen, void *data) {
|
||||
spellbook *sb;
|
||||
cb_get_kv(match, &sb, sizeof(sb));
|
||||
free_spellbook(sb);
|
||||
const sb_entry *ent = (const sb_entry *)match;
|
||||
free_spellbook(ent->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,18 @@ void test_updatespells(CuTest * tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
void test_spellbooks(CuTest * tc)
|
||||
static void test_get_spellbook(CuTest * tc)
|
||||
{
|
||||
spellbook *sb;
|
||||
|
||||
test_setup();
|
||||
CuAssertPtrNotNull(tc, sb = get_spellbook("hodorhodorhodor"));
|
||||
CuAssertPtrEquals(tc, sb, get_spellbook("hodorhodorhodor"));
|
||||
CuAssertTrue(tc, sb != get_spellbook("hodor"));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_spellbooks(CuTest * tc)
|
||||
{
|
||||
spell *sp;
|
||||
spellbook *herp, *derp;
|
||||
|
@ -445,24 +456,6 @@ static void test_max_spellpoints(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_familiar_mage(CuTest *tc) {
|
||||
unit *um, *uf, *ut;
|
||||
test_setup();
|
||||
um = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
uf = test_create_unit(um->faction, um->region);
|
||||
ut = test_create_unit(um->faction, um->region);
|
||||
set_number(ut, 0);
|
||||
CuAssertTrue(tc, create_newfamiliar(um, uf));
|
||||
CuAssertTrue(tc, is_familiar(uf));
|
||||
CuAssertTrue(tc, !is_familiar(um));
|
||||
CuAssertPtrEquals(tc, um, get_familiar_mage(uf));
|
||||
CuAssertPtrEquals(tc, uf, get_familiar(um));
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, give_men(1, um, ut, NULL));
|
||||
CuAssertPtrEquals(tc, ut, get_familiar_mage(uf));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_illusioncastle(CuTest *tc)
|
||||
{
|
||||
building *b;
|
||||
|
@ -490,6 +483,7 @@ CuSuite *get_magic_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_multi_cast);
|
||||
SUITE_ADD_TEST(suite, test_updatespells);
|
||||
SUITE_ADD_TEST(suite, test_spellbooks);
|
||||
SUITE_ADD_TEST(suite, test_get_spellbook);
|
||||
SUITE_ADD_TEST(suite, test_pay_spell);
|
||||
SUITE_ADD_TEST(suite, test_pay_spell_failure);
|
||||
SUITE_ADD_TEST(suite, test_getspell_unit);
|
||||
|
@ -502,6 +496,5 @@ CuSuite *get_magic_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_magic_resistance);
|
||||
SUITE_ADD_TEST(suite, test_max_spellpoints);
|
||||
SUITE_ADD_TEST(suite, test_illusioncastle);
|
||||
DISABLE_TEST(suite, test_familiar_mage);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||
| | Enno Rehling <enno@eressea.de>
|
||||
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
|
||||
|
@ -14,7 +14,7 @@
|
|||
#include <kernel/config.h>
|
||||
#include "xmas.h"
|
||||
|
||||
/* kernel includes */
|
||||
/* kernel includes */
|
||||
#include <kernel/building.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/item.h>
|
||||
|
@ -50,10 +50,7 @@ static void xmasgate_write(const trigger * t, struct storage *store)
|
|||
|
||||
static int xmasgate_read(trigger * t, struct gamedata *data)
|
||||
{
|
||||
int bc =
|
||||
read_reference(&t->data.v, data, read_building_reference,
|
||||
resolve_building);
|
||||
if (bc == 0 && !t->data.v) {
|
||||
if (read_building_reference(data, (building **)&t->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -612,7 +612,7 @@ static void recruit_dracoids(unit * dragon, int size)
|
|||
|
||||
name_unit(un);
|
||||
change_money(dragon, -un->number * 50);
|
||||
equip_unit(un, get_equipment("recruited_dracoid"));
|
||||
equip_unit(un, get_equipment("new_dracoid"));
|
||||
|
||||
setstatus(un, ST_FIGHT);
|
||||
for (weapon = un->items; weapon; weapon = weapon->next) {
|
||||
|
@ -863,7 +863,7 @@ static int nrand(int start, int sub)
|
|||
unit *spawn_seaserpent(region *r, faction *f) {
|
||||
unit *u = create_unit(r, f, 1, get_race(RC_SEASERPENT), 0, NULL, NULL);
|
||||
fset(u, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(u, get_equipment("monster_seaserpent"));
|
||||
equip_unit(u, get_equipment("seed_seaserpent"));
|
||||
return u;
|
||||
}
|
||||
|
||||
|
@ -894,7 +894,7 @@ void spawn_dragons(void)
|
|||
u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL);
|
||||
}
|
||||
fset(u, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(u, get_equipment("monster_dragon"));
|
||||
equip_unit(u, get_equipment("seed_dragon"));
|
||||
|
||||
log_debug("spawning %d %s in %s.\n", u->number,
|
||||
LOC(default_locale,
|
||||
|
@ -1132,7 +1132,7 @@ faction *get_or_create_monsters(void)
|
|||
if (!f) {
|
||||
const race *rc = rc_get_or_create("dragon");
|
||||
const char *email = config_get("monster.email");
|
||||
f = addfaction(email ? email : "noreply@eressea.de", NULL, rc, default_locale, 0);
|
||||
f = addfaction(email ? email : NULL, NULL, rc, default_locale, 0);
|
||||
renumber_faction(f, MONSTER_ID);
|
||||
faction_setname(f, "Monster");
|
||||
fset(f, FFL_NPC | FFL_NOIDLEOUT);
|
||||
|
|
|
@ -263,7 +263,7 @@ static void get_villagers(region * r, unit * u)
|
|||
u);
|
||||
leave(newunit, true);
|
||||
fset(newunit, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(newunit, get_equipment("random_villagers"));
|
||||
equip_unit(newunit, get_equipment("rand_villagers"));
|
||||
}
|
||||
|
||||
static void get_allies(region * r, unit * u)
|
||||
|
@ -282,7 +282,7 @@ static void get_allies(region * r, unit * u)
|
|||
if (get_money(u) / u->number < 100 + rng_int() % 200)
|
||||
return;
|
||||
name = "random_plain_men";
|
||||
equip = "random_plain";
|
||||
equip = "rand_plain";
|
||||
number = rng_int() % 8 + 2;
|
||||
break;
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_forest_men";
|
||||
equip = "random_forest";
|
||||
equip = "rand_forest";
|
||||
number = rng_int() % 6 + 2;
|
||||
}
|
||||
break;
|
||||
|
@ -303,7 +303,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_swamp_men";
|
||||
equip = "random_swamp";
|
||||
equip = "rand_swamp";
|
||||
number = rng_int() % 6 + 2;
|
||||
break;
|
||||
|
||||
|
@ -312,7 +312,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_desert_men";
|
||||
equip = "random_desert";
|
||||
equip = "rand_desert";
|
||||
number = rng_int() % 12 + 2;
|
||||
break;
|
||||
|
||||
|
@ -321,7 +321,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_highland_men";
|
||||
equip = "random_highland";
|
||||
equip = "rand_highland";
|
||||
number = rng_int() % 8 + 2;
|
||||
break;
|
||||
|
||||
|
@ -330,7 +330,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_mountain_men";
|
||||
equip = "random_mountain";
|
||||
equip = "rand_mountain";
|
||||
number = rng_int() % 6 + 2;
|
||||
break;
|
||||
|
||||
|
@ -339,7 +339,7 @@ static void get_allies(region * r, unit * u)
|
|||
return;
|
||||
}
|
||||
name = "random_glacier_men";
|
||||
equip = "random_glacier";
|
||||
equip = "rand_glacier";
|
||||
number = rng_int() % 4 + 2;
|
||||
break;
|
||||
|
||||
|
|
|
@ -1069,15 +1069,15 @@ void report_region(struct stream *out, const region * r, faction * f)
|
|||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
|
||||
if (r->display && r->display[0]) {
|
||||
if (r->land && r->land->display && r->land->display[0]) {
|
||||
bytes = (int)strlcpy(bufp, " ", size);
|
||||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
bytes = (int)strlcpy(bufp, r->display, size);
|
||||
bytes = (int)strlcpy(bufp, r->land->display, size);
|
||||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
|
||||
n = r->display[strlen(r->display) - 1];
|
||||
n = r->land->display[strlen(r->land->display) - 1];
|
||||
if (n != '!' && n != '?' && n != '.') {
|
||||
bytes = (int)strlcpy(bufp, ".", size);
|
||||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
|
|
|
@ -1616,11 +1616,13 @@ int reports(void)
|
|||
}
|
||||
|
||||
for (f = factions; f; f = f->next) {
|
||||
int error = write_reports(f, ltime);
|
||||
if (error)
|
||||
retval = error;
|
||||
if (mailit)
|
||||
write_script(mailit, f);
|
||||
if (f->email && !fval(f, FFL_NPC)) {
|
||||
int error = write_reports(f, ltime);
|
||||
if (error)
|
||||
retval = error;
|
||||
if (mailit)
|
||||
write_script(mailit, f);
|
||||
}
|
||||
}
|
||||
if (mailit)
|
||||
fclose(mailit);
|
||||
|
@ -1701,7 +1703,7 @@ static void var_free_regions(variant x) /*-V524 */
|
|||
|
||||
const char *trailinto(const region * r, const struct locale *lang)
|
||||
{
|
||||
char ref[32];
|
||||
static char ref[32];
|
||||
const char *s;
|
||||
if (r) {
|
||||
const char *tname = terrain_name(r);
|
||||
|
@ -2145,23 +2147,6 @@ static void eval_int36(struct opstack **stack, const void *userdata)
|
|||
|
||||
/*** END MESSAGE RENDERING ***/
|
||||
|
||||
#include <util/nrmessage.h>
|
||||
|
||||
static void log_orders(const struct message *msg)
|
||||
{
|
||||
char buffer[4096];
|
||||
int i;
|
||||
|
||||
for (i = 0; i != msg->type->nparameters; ++i) {
|
||||
if (msg->type->types[i]->copy == &var_copy_order) {
|
||||
const char *section = nr_section(msg);
|
||||
nr_render(msg, default_locale, buffer, sizeof(buffer), NULL);
|
||||
log_debug("MESSAGE [%s]: %s\n", section, buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int stream_printf(struct stream * out, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -2224,8 +2209,6 @@ void register_reports(void)
|
|||
register_argtype("items", var_free_resources, var_copy_items, VAR_VOIDPTR);
|
||||
register_argtype("regions", var_free_regions, NULL, VAR_VOIDPTR);
|
||||
|
||||
msg_log_create = &log_orders;
|
||||
|
||||
/* register functions that turn message contents to readable strings */
|
||||
add_function("alliance", &eval_alliance);
|
||||
add_function("region", &eval_region);
|
||||
|
|
|
@ -279,13 +279,13 @@ static void test_bufunit(CuTest *tc) {
|
|||
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
|
||||
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv.", buffer);
|
||||
|
||||
set_level(u, SK_SAILING, 1);
|
||||
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
|
||||
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Segeln 1.", buffer);
|
||||
|
||||
set_level(u, SK_ALCHEMY, 1);
|
||||
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
|
||||
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Segeln 1, Alchemie 2.", buffer);
|
||||
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2.", buffer);
|
||||
|
||||
set_level(u, SK_SAILING, 1);
|
||||
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
|
||||
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2, Segeln 1.", buffer);
|
||||
|
||||
f = test_create_faction(0);
|
||||
f->locale = get_or_create_locale("de");
|
||||
|
|
43
src/spells.c
43
src/spells.c
|
@ -519,7 +519,7 @@ static void make_familiar(unit * familiar, unit * mage)
|
|||
const struct equipment *eq;
|
||||
char eqname[64];
|
||||
const race * rc = u_race(familiar);
|
||||
snprintf(eqname, sizeof(eqname), "%s_familiar", rc->_name);
|
||||
snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq != NULL) {
|
||||
equip_items(&familiar->items, eq);
|
||||
|
@ -2892,47 +2892,20 @@ static curse *mk_deathcloud(unit * mage, region * r, double force, int duration)
|
|||
return c;
|
||||
}
|
||||
|
||||
#define COMPAT_DEATHCLOUD
|
||||
#ifdef COMPAT_DEATHCLOUD
|
||||
static int dc_read_compat(struct attrib *a, void *target, gamedata *data)
|
||||
/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
|
||||
{
|
||||
struct storage *store = data->store;
|
||||
region *r = NULL;
|
||||
unit *u;
|
||||
variant var;
|
||||
int duration;
|
||||
float strength;
|
||||
int rx, ry;
|
||||
|
||||
UNUSED_ARG(a);
|
||||
UNUSED_ARG(target);
|
||||
READ_INT(store, &duration);
|
||||
READ_FLT(store, &strength);
|
||||
READ_INT(store, &var.i);
|
||||
u = findunit(var.i);
|
||||
|
||||
/* this only affects really old data. no need to change: */
|
||||
READ_INT(store, &rx);
|
||||
READ_INT(store, &ry);
|
||||
r = findregion(rx, ry);
|
||||
|
||||
if (r != NULL) {
|
||||
double effect;
|
||||
curse *c;
|
||||
|
||||
effect = strength;
|
||||
c =
|
||||
create_curse(u, &r->attribs, &ct_deathcloud, strength * 2, duration,
|
||||
effect, 0);
|
||||
c->data.v = r;
|
||||
if (u == NULL) {
|
||||
ur_add(var, &c->magician, resolve_unit);
|
||||
}
|
||||
}
|
||||
return AT_READ_FAIL; /* we don't care for the attribute. */
|
||||
READ_INT(store, NULL);
|
||||
READ_FLT(store, NULL);
|
||||
READ_INT(store, NULL);
|
||||
READ_INT(store, NULL);
|
||||
READ_INT(store, NULL);
|
||||
return AT_READ_DEPR; /* we don't care for the attribute. */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Name: Todeswolke
|
||||
|
@ -6705,9 +6678,7 @@ void register_spells(void)
|
|||
{
|
||||
register_borders();
|
||||
|
||||
#ifdef COMPAT_DEATHCLOUD
|
||||
at_deprecate("zauber_todeswolke", dc_read_compat);
|
||||
#endif
|
||||
|
||||
/* init_firewall(); */
|
||||
ct_register(&ct_firewall);
|
||||
|
|
|
@ -92,11 +92,9 @@ static void wall_read(connection * b, gamedata * data)
|
|||
static wall_data dummy;
|
||||
wall_data *fd = b->data.v ? (wall_data *)b->data.v : &dummy;
|
||||
|
||||
read_reference(&fd->mage, data, read_unit_reference, resolve_unit);
|
||||
read_unit_reference(data, &fd->mage, NULL);
|
||||
READ_INT(data->store, &fd->force);
|
||||
if (data->version >= NOBORDERATTRIBS_VERSION) {
|
||||
READ_INT(data->store, &fd->countdown);
|
||||
}
|
||||
READ_INT(data->store, &fd->countdown);
|
||||
fd->active = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void spawn_braineaters(float chance)
|
|||
unit *u =
|
||||
create_unit(r, f0, 1 + rng_int() % 10 + rng_int() % 10,
|
||||
get_race(RC_HIRNTOETER), 0, NULL, NULL);
|
||||
equip_unit(u, get_equipment("monster_braineater"));
|
||||
equip_unit(u, get_equipment("seed_braineater"));
|
||||
|
||||
next = rng_int() % (int)(chance * 100);
|
||||
}
|
||||
|
|
|
@ -83,16 +83,10 @@ static void changefaction_write(const trigger * t, struct storage *store)
|
|||
|
||||
static int changefaction_read(trigger * t, gamedata *data)
|
||||
{
|
||||
variant var;
|
||||
changefaction_data *td = (changefaction_data *)t->data.v;
|
||||
|
||||
read_reference(&td->unit, data, read_unit_reference, resolve_unit);
|
||||
var = read_faction_reference(data);
|
||||
if (var.i == 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
ur_add(var, &td->faction, resolve_faction);
|
||||
return AT_READ_OK;
|
||||
read_unit_reference(data, &td->unit, NULL);
|
||||
return read_faction_reference(data, &td->faction, NULL) > 0 ? AT_READ_OK : AT_READ_FAIL;
|
||||
}
|
||||
|
||||
trigger_type tt_changefaction = {
|
||||
|
|
|
@ -89,9 +89,9 @@ static void changerace_write(const trigger * t, struct storage *store)
|
|||
static int changerace_read(trigger * t, gamedata *data)
|
||||
{
|
||||
changerace_data *td = (changerace_data *)t->data.v;
|
||||
read_reference(&td->u, data, read_unit_reference, resolve_unit);
|
||||
td->race = (const struct race *)read_race_reference(data->store).v;
|
||||
td->irace = (const struct race *)read_race_reference(data->store).v;
|
||||
read_unit_reference(data, &td->u, NULL);
|
||||
td->race = read_race_reference(data->store);
|
||||
td->irace = read_race_reference(data->store);
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,9 +70,7 @@ static void clonedied_write(const trigger * t, struct storage *store)
|
|||
|
||||
static int clonedied_read(trigger * t, gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&t->data.v, data, read_unit_reference, resolve_unit);
|
||||
if (result == 0 && t->data.v == NULL) {
|
||||
if (read_unit_reference(data, (unit **)&t->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -98,8 +98,8 @@ static int createcurse_read(trigger * t, gamedata *data)
|
|||
char zText[128];
|
||||
float flt;
|
||||
|
||||
read_reference(&td->mage, data, read_unit_reference, resolve_unit);
|
||||
read_reference(&td->target, data, read_unit_reference, resolve_unit);
|
||||
read_unit_reference(data, &td->mage, NULL);
|
||||
read_unit_reference(data, &td->target, NULL);
|
||||
|
||||
READ_TOK(data->store, zText, sizeof(zText));
|
||||
td->type = ct_find(zText);
|
||||
|
|
|
@ -90,22 +90,16 @@ static void createunit_write(const trigger * t, struct storage *store)
|
|||
static int createunit_read(trigger * t, gamedata *data)
|
||||
{
|
||||
createunit_data *td = (createunit_data *)t->data.v;
|
||||
variant var;
|
||||
int id;
|
||||
int result = AT_READ_OK;
|
||||
var = read_faction_reference(data);
|
||||
if (var.i > 0) {
|
||||
td->f = findfaction(var.i);
|
||||
if (!td->f) {
|
||||
ur_add(var, &td->f, resolve_faction);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
id = read_faction_reference(data, &td->f, NULL);
|
||||
if (id <= 0) {
|
||||
result = AT_READ_FAIL;
|
||||
}
|
||||
|
||||
read_reference(&td->r, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
td->race = (const struct race *)read_race_reference(data->store).v;
|
||||
read_region_reference(data, &td->r, NULL);
|
||||
td->race = read_race_reference(data->store);
|
||||
if (!td->race) {
|
||||
result = AT_READ_FAIL;
|
||||
}
|
||||
|
|
|
@ -74,16 +74,11 @@ static void gate_write(const trigger * t, struct storage *store)
|
|||
static int gate_read(trigger * t, gamedata *data)
|
||||
{
|
||||
gate_data *gd = (gate_data *)t->data.v;
|
||||
int bc = read_building_reference(data, &gd->gate, NULL);
|
||||
int rc = read_region_reference(data, &gd->target, NULL);
|
||||
|
||||
int bc =
|
||||
read_reference(&gd->gate, data, read_building_reference, resolve_building);
|
||||
int rc =
|
||||
read_reference(&gd->target, data, read_region_reference,
|
||||
RESOLVE_REGION(data->version));
|
||||
|
||||
if (bc == 0 && rc == 0) {
|
||||
if (!gd->gate || !gd->target)
|
||||
return AT_READ_FAIL;
|
||||
if (bc <= 0 && rc <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
|
|
@ -86,15 +86,16 @@ static int giveitem_read(trigger * t, gamedata *data)
|
|||
{
|
||||
giveitem_data *td = (giveitem_data *)t->data.v;
|
||||
char zText[128];
|
||||
int result;
|
||||
|
||||
int result = read_reference(&td->u, data, read_unit_reference, resolve_unit);
|
||||
result = read_unit_reference(data, &td->u, NULL);
|
||||
|
||||
READ_INT(data->store, &td->number);
|
||||
READ_TOK(data->store, zText, sizeof(zText));
|
||||
td->itype = it_find(zText);
|
||||
assert(td->itype);
|
||||
|
||||
if (result == 0 && td->u == NULL) {
|
||||
if (result == 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -60,9 +60,7 @@ static void killunit_write(const trigger * t, struct storage *store)
|
|||
|
||||
static int killunit_read(trigger * t, gamedata *data)
|
||||
{
|
||||
int result = read_reference(&t->data.v, data, read_unit_reference,
|
||||
resolve_unit);
|
||||
if (result == 0 && t->data.v == NULL) {
|
||||
if (read_unit_reference(data, (unit **)&t->data.v, NULL) == 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -125,11 +125,8 @@ static void shock_write(const trigger * t, struct storage *store)
|
|||
}
|
||||
}
|
||||
|
||||
static int shock_read(trigger * t, gamedata *data)
|
||||
{
|
||||
int result =
|
||||
read_reference(&t->data.v, data, read_unit_reference, resolve_unit);
|
||||
if (result == 0 && t->data.v == NULL) {
|
||||
static int shock_read(trigger * t, gamedata *data) {
|
||||
if (read_unit_reference(data, (unit **)&t->data.v, NULL) <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
return AT_READ_OK;
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
|
||||
#include <stream.h>
|
||||
|
||||
#define INTPAK_VERSION 329 /* in binary, ints can get packed. starting with E2/572 */
|
||||
#define NOZEROIDS_VERSION 330 /* 2008-05-16 zero is not a valid ID for anything (including factions) */
|
||||
#define NOBORDERATTRIBS_VERSION 331 /* 2008-05-17 connection::attribs has been moved to userdata */
|
||||
#define UIDHASH_VERSION 332 /* 2008-05-22 borders use the region.uid to store */
|
||||
#define UIDHASH_VERSION 332 /* 2008-05-22 = 572 borders use the region.uid to store */
|
||||
#define REGIONOWNER_VERSION 333 /* 2009-05-14 regions have owners and morale */
|
||||
#define ALLIANCELEADER_VERSION 333 /* alliances have a leader */
|
||||
#define CURSEFLOAT_VERSION 334 /* all curse-effects are float */
|
||||
|
@ -36,12 +33,14 @@
|
|||
#define NOLANDITEM_VERSION 356 /* land_region has no items */
|
||||
#define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */
|
||||
#define SORTKEYS_VERSION 358 /* at_keys is sorted */
|
||||
#define FAMILIAR_FIX_VERSION 359 /* at_keys is sorted */
|
||||
#define FAMILIAR_FIX_VERSION 359 /* familiar links are fixed */
|
||||
#define SKILLSORT_VERSION 360 /* u->skills is sorted */
|
||||
#define LANDDISPLAY_VERSION 360 /* r.display is now in r.land.display */
|
||||
/* unfinished: */
|
||||
#define CRYPT_VERSION 400 /* passwords are encrypted */
|
||||
|
||||
#define RELEASE_VERSION FAMILIAR_FIX_VERSION /* current datafile */
|
||||
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
|
||||
#define RELEASE_VERSION SKILLSORT_VERSION /* current datafile */
|
||||
#define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */
|
||||
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||
|
||||
#define STREAM_VERSION 2 /* internal encoding of binary files */
|
||||
|
|
|
@ -17,80 +17,85 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
**/
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include <selist.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "resolve.h"
|
||||
#include "storage.h"
|
||||
#include "variant.h"
|
||||
|
||||
typedef struct unresolved {
|
||||
void *ptrptr;
|
||||
/* address to pass to the resolve-function */
|
||||
variant data;
|
||||
int id;
|
||||
/* information on how to resolve the missing object */
|
||||
resolve_fun resolve;
|
||||
/* function to resolve the unknown object */
|
||||
selist *addrs;
|
||||
/* address to pass to the resolve-function */
|
||||
} unresolved;
|
||||
|
||||
#define BLOCKSIZE 1024
|
||||
static unresolved *ur_list;
|
||||
static unresolved *ur_begin;
|
||||
static unresolved *ur_current;
|
||||
#define HASHSIZE 1024 /* must be a power of 2 */
|
||||
static unresolved ur_hash[HASHSIZE];
|
||||
|
||||
variant read_int(struct storage *store)
|
||||
{
|
||||
variant var;
|
||||
READ_INT(store, &var.i);
|
||||
return var;
|
||||
int ur_key(int id) {
|
||||
int h = id ^ (id >> 16);
|
||||
return h & (HASHSIZE - 1);
|
||||
}
|
||||
|
||||
int
|
||||
read_reference(void *address, struct gamedata * data, read_fun reader,
|
||||
resolve_fun resolver)
|
||||
void ur_add(int id, void **addr, resolve_fun fun)
|
||||
{
|
||||
variant var = reader(data);
|
||||
int result = resolver(var, address);
|
||||
if (result != 0) {
|
||||
ur_add(var, address, resolver);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int h, i;
|
||||
|
||||
void ur_add(variant data, void *ptrptr, resolve_fun fun)
|
||||
{
|
||||
assert(ptrptr);
|
||||
if (ur_list == NULL) {
|
||||
ur_list = malloc(BLOCKSIZE * sizeof(unresolved));
|
||||
ur_begin = ur_current = ur_list;
|
||||
}
|
||||
else if (ur_current - ur_begin == BLOCKSIZE - 1) {
|
||||
ur_begin = malloc(BLOCKSIZE * sizeof(unresolved));
|
||||
ur_current->data.v = ur_begin;
|
||||
ur_current = ur_begin;
|
||||
}
|
||||
ur_current->data = data;
|
||||
ur_current->resolve = fun;
|
||||
ur_current->ptrptr = ptrptr;
|
||||
|
||||
++ur_current;
|
||||
ur_current->resolve = NULL;
|
||||
ur_current->data.v = NULL;
|
||||
}
|
||||
|
||||
void resolve(void)
|
||||
{
|
||||
unresolved *ur = ur_list;
|
||||
while (ur) {
|
||||
if (ur->resolve == NULL) {
|
||||
ur = ur->data.v;
|
||||
free(ur_list);
|
||||
ur_list = ur;
|
||||
continue;
|
||||
assert(id > 0);
|
||||
assert(addr);
|
||||
assert(!*addr);
|
||||
|
||||
h = ur_key(id);
|
||||
for (i = 0; i != HASHSIZE; ++i) {
|
||||
int k = h + i;
|
||||
if (k >= HASHSIZE) k -= HASHSIZE;
|
||||
if (ur_hash[k].id <= 0) {
|
||||
ur_hash[k].id = id;
|
||||
ur_hash[k].resolve = fun;
|
||||
selist_push(&ur_hash[k].addrs, addr);
|
||||
return;
|
||||
}
|
||||
if (ur_hash[k].id == id && ur_hash[k].resolve == fun) {
|
||||
ur_hash[k].resolve = fun;
|
||||
selist_push(&ur_hash[k].addrs, addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(!"hash table is full");
|
||||
}
|
||||
|
||||
static bool addr_cb(void *data, void *more) {
|
||||
void **addr = (void **)data;
|
||||
*addr = more;
|
||||
return true;
|
||||
}
|
||||
|
||||
void resolve(int id, void *data)
|
||||
{
|
||||
int h, i;
|
||||
h = ur_key(id);
|
||||
|
||||
for (i = 0; i != HASHSIZE; ++i) {
|
||||
int k = h + i;
|
||||
|
||||
if (k >= HASHSIZE) k -= HASHSIZE;
|
||||
if (ur_hash[k].id == 0) break;
|
||||
else if (ur_hash[k].id == id) {
|
||||
if (ur_hash[k].resolve) {
|
||||
data = ur_hash[k].resolve(id, data);
|
||||
}
|
||||
selist_foreach_ex(ur_hash[k].addrs, addr_cb, data);
|
||||
selist_free(ur_hash[k].addrs);
|
||||
ur_hash[k].addrs = NULL;
|
||||
ur_hash[k].id = -1;
|
||||
}
|
||||
assert(ur->ptrptr);
|
||||
ur->resolve(ur->data, ur->ptrptr);
|
||||
++ur;
|
||||
}
|
||||
free(ur_list);
|
||||
ur_list = NULL;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifndef RESOLVE_H
|
||||
#define RESOLVE_H
|
||||
|
||||
#include "variant.h"
|
||||
struct storage;
|
||||
struct gamedata;
|
||||
|
||||
|
@ -27,15 +26,11 @@ struct gamedata;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int(*resolve_fun) (variant data, void *address);
|
||||
typedef variant(*read_fun) (struct gamedata * data);
|
||||
extern int read_reference(void *address, struct gamedata *data,
|
||||
read_fun reader, resolve_fun resolver);
|
||||
typedef void *(*resolve_fun) (int id, void *data);
|
||||
typedef int(*read_fun) (struct gamedata * data);
|
||||
|
||||
extern void ur_add(variant data, void *address, resolve_fun fun);
|
||||
extern void resolve(void);
|
||||
|
||||
extern variant read_int(struct storage *store);
|
||||
void ur_add(int id, void **addr, resolve_fun fun);
|
||||
void resolve(int id, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ void opstack_push(opstack ** stackp, variant data)
|
|||
** static buffer malloc
|
||||
**/
|
||||
|
||||
#define BBUFSIZE 0x20000
|
||||
#define BBUFSIZE 0x10000
|
||||
static struct {
|
||||
char *begin;
|
||||
char *end;
|
||||
|
@ -81,16 +81,13 @@ static struct {
|
|||
|
||||
char *balloc(size_t size)
|
||||
{
|
||||
static int init = 0; /* STATIC_XCALL: used across calls */
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
init = 1;
|
||||
buffer.current = buffer.begin = malloc(BBUFSIZE * sizeof(char));
|
||||
buffer.end = buffer.begin + BBUFSIZE;
|
||||
}
|
||||
if (buffer.current + size > buffer.end) {
|
||||
/* out of memory! */
|
||||
return NULL;
|
||||
}
|
||||
assert(buffer.current + size <= buffer.end || !"balloc is out of memory");
|
||||
buffer.last = buffer.current;
|
||||
buffer.current += size;
|
||||
return buffer.last;
|
||||
|
@ -99,6 +96,7 @@ char *balloc(size_t size)
|
|||
void bfree(char *c)
|
||||
/* only release this memory if it was part of the last allocation
|
||||
* that's a joke, but who cares.
|
||||
* I'm afraid I don't get the joke.
|
||||
*/
|
||||
{
|
||||
if (c >= buffer.last && c < buffer.current)
|
||||
|
|
|
@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include "assert.h"
|
||||
#include "log.h"
|
||||
#include "bsdstring.h"
|
||||
#include "unicode.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -211,7 +212,7 @@ void addtoken(tnode ** root, const char *str, variant id)
|
|||
if (lcs == replace[i].ucs) {
|
||||
char zText[1024];
|
||||
memcpy(zText, replace[i].str, 3);
|
||||
strcpy(zText + 2, (const char *)str + len);
|
||||
strlcpy(zText + 2, (const char *)str + len, sizeof(zText)-2);
|
||||
addtoken(root, zText, id);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -96,36 +96,15 @@ static void wormhole_write(const struct attrib *a, const void *owner, struct sto
|
|||
write_region_reference(exit, store);
|
||||
}
|
||||
|
||||
/** conversion code, turn 573, 2008-05-23 */
|
||||
static int resolve_exit(variant id, void *address)
|
||||
{
|
||||
building *b = findbuilding(id.i);
|
||||
region **rp = address;
|
||||
if (b) {
|
||||
*rp = b->region;
|
||||
return 0;
|
||||
}
|
||||
*rp = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int wormhole_read(struct attrib *a, void *owner, struct gamedata *data)
|
||||
{
|
||||
storage *store = data->store;
|
||||
resolve_fun resolver = (data->version < UIDHASH_VERSION)
|
||||
? resolve_exit : resolve_region_id;
|
||||
read_fun reader = (data->version < UIDHASH_VERSION)
|
||||
? read_building_reference : read_region_reference;
|
||||
int id;
|
||||
|
||||
if (data->version < ATTRIBOWNER_VERSION) {
|
||||
READ_INT(store, NULL);
|
||||
READ_INT(data->store, NULL);
|
||||
}
|
||||
if (read_reference(&a->data.v, data, reader, resolver) == 0) {
|
||||
if (!a->data.v) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
}
|
||||
return AT_READ_OK;
|
||||
id = read_region_reference(data, (region **)&a->data.v, NULL);
|
||||
return (id <= 0) ? AT_READ_FAIL : AT_READ_OK;
|
||||
}
|
||||
|
||||
static attrib_type at_wormhole = {
|
||||
|
|
Loading…
Reference in a new issue