Merge branch 'badgerman-version-3-4' into version-3-4

This commit is contained in:
Enno Rehling 2015-01-29 18:04:09 +01:00
commit fb2200f79f
80 changed files with 784 additions and 718 deletions

View file

@ -58,6 +58,7 @@
<order name="tax" disable="yes"/> <order name="tax" disable="yes"/>
<order name="entertain" disable="yes"/> <order name="entertain" disable="yes"/>
<order name="sell" disable="yes"/> <order name="sell" disable="yes"/>
<order name="origin" disable="yes"/>
<skill name="armorer" enable="true"/> <skill name="armorer" enable="true"/>
<skill name="bow" enable="true"/> <skill name="bow" enable="true"/>

View file

@ -9,7 +9,7 @@ memcheck = 0
locales = de,en locales = de,en
[lua] [lua]
install = ../git install = .
paths = lunit:scripts paths = lunit:scripts
maxnmrs = 20 maxnmrs = 20
rules = e2 rules = e2

View file

@ -1,16 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<rewriteURI
uriStartString="config:///game/"
rewritePrefix="../res/eressea/" />
<rewriteURI
uriStartString="config:///default/"
rewritePrefix="../res/" />
<rewriteURI
uriStartString="config:///core/"
rewritePrefix="../core/res/" />
</catalog>

View file

@ -1,114 +0,0 @@
<?xml version="1.0"?>
<eressea xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="config:///core/messages.xml"/>
<!-- Localization -->
<xi:include href="config:///core/de/strings.xml"/>
<xi:include href="config:///core/en/strings.xml"/>
<xi:include href="config:///game/spellinfo.xml" />
<xi:include href="config:///core/common/items.xml" />
<xi:include href="config:///core/common/armor.xml" />
<xi:include href="config:///core/common/weapons.xml" />
<xi:include href="config:///core/common/resources.xml" />
<xi:include href="config:///core/common/luxuries.xml" />
<xi:include href="config:///core/common/herbs.xml" />
<xi:include href="config:///core/common/potions.xml" />
<xi:include href="config:///core/spoils.xml"/>
<xi:include href="config:///game/races.xml"/>
<xi:include href="config:///core/prefixes.xml"/>
<xi:include href="config:///core/ships.xml"/>
<xi:include href="config:///core/common/buildings.xml"/>
<xi:include href="config:///game/familiars.xml"/>
<xi:include href="config:///core/terrains.xml"/>
<xi:include href="config:///game/terrains.xml"/>
<xi:include href="config:///game/artrewards.xml"/>
<xi:include href="config:///game/buildings.xml"/>
<xi:include href="config:///core/calendar.xml"/>
<calendar name="secondage" newyear="month_1" start="184"/>
<xi:include href="config:///game/equipment.xml"/>
<xi:include href="config:///game/items.xml"/>
<xi:include href="config:///game/spells.xml"/>
<xi:include href="config:///game/strings.xml"/>
<xi:include href="config:///default/adamantium.xml"/>
<equipment>
<set name="first_unit">
<item name="conquesttoken" amount="1"/>
<item name="log" amount="30"/>
<item name="stone" amount="30"/>
<item name="money" amount="4200"/>
</set>
<set name="new_faction">
<item name="adamantium" amount="1"/>
</set>
</equipment>
<xi:include href="config:///default/names-undead.xml"/>
<xi:include href="config:///default/names-skeletons.xml"/>
<xi:include href="config:///default/names-zombies.xml"/>
<xi:include href="config:///default/names-ghouls.xml"/>
<xi:include href="config:///default/names-dragons.xml"/>
<game name="Eressea">
<!-- Game specific settings -->
<skill name="alchemy" enable="true"/>
<skill name="crossbow" enable="true"/>
<skill name="mining" enable="true"/>
<skill name="bow" enable="true"/>
<skill name="building" enable="true"/>
<skill name="trade" enable="true"/>
<skill name="forestry" enable="true"/>
<skill name="catapult" enable="true"/>
<skill name="herbalism" enable="true"/>
<skill name="magic" enable="true"/>
<skill name="training" enable="true"/>
<skill name="riding" enable="true"/>
<skill name="armorer" enable="true"/>
<skill name="shipcraft" enable="true"/>
<skill name="melee" enable="true"/>
<skill name="sailing" enable="true"/>
<skill name="polearm" enable="true"/>
<skill name="espionage" enable="true"/>
<skill name="quarrying" enable="true"/>
<skill name="roadwork" enable="true"/>
<skill name="tactics" enable="true"/>
<skill name="stealth" enable="true"/>
<skill name="entertainment" enable="true"/>
<skill name="weaponsmithing" enable="true"/>
<skill name="cartmaking" enable="true"/>
<skill name="perception" enable="true"/>
<skill name="taxation" enable="true"/>
<skill name="stamina" enable="true"/>
<skill name="unarmed" enable="true"/>
<param name="NewbieImmunity" value="8"/>
<param name="modules.wormholes" value="1"/>
<param name="entertain.base" value="0"/>
<param name="entertain.perlevel" value="20"/>
<param name="nmr.timeout" value="5"/>
<param name="nmr.removenewbie" value="10"/>
<param name="GiveRestriction" value="3"/>
<param name="hunger.long" value="1"/>
<param name="init_spells" value="0"/>
<param name="rules.check_overload" value="0"/>
<param name="rules.limit.faction" value="2500"/>
<param name="rules.maxskills.magic" value="5"/>
</game>
<strings>
<string name="mailto">
<text locale="de">eressea-server@eressea.de</text>
<text locale="en">eressea-server@eressea.de</text>
</string>
<string name="newbie_info_1">
<text locale="de">Bitte denke daran, deine Befehle mit dem Betreff
ERESSEA BEFEHLE an eressea-server@eressea.de zu senden.</text>
<text locale="en">Remember to send your orders to
eressea-server@eressea.de with the subject ERESSEA ORDERS.</text>
</string>
<string name="mailcmd">
<text locale="de">ERESSEA BEFEHLE</text>
<text locale="en">ERESSEA ORDERS</text>
</string>
</strings>
</eressea>

View file

@ -1,16 +0,0 @@
[eressea]
base = .
report = reports
verbose = 0
lomem = 0
debug = 0
memcheck = 0
locales = de,en
[config]
rules = eressea
source_dir = ..
maxnmrs = 10
[editor]
color = 1

View file

@ -1,2 +0,0 @@
require "setup"
run_tests()

View file

@ -1,14 +0,0 @@
local srcpath = config.source_dir
local respath = srcpath .. '/res'
local paths = {
'scripts/?.lua',
'core/scripts/?.lua',
'lunit/?.lua'
}
for idx, path in pairs(paths) do
package.path = srcpath .. '/' .. path .. ';' .. package.path
end
assert(read_xml())
require "init"

View file

@ -1,16 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<rewriteURI
uriStartString="config:///game/"
rewritePrefix="../res/e3a/" />
<rewriteURI
uriStartString="config:///default/"
rewritePrefix="../res/" />
<rewriteURI
uriStartString="config:///core/"
rewritePrefix="../core/res/" />
</catalog>

View file

@ -1,182 +0,0 @@
<?xml version="1.0"?>
<eressea xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="config:///core/messages.xml"/>
<xi:include href="config:///core/de/strings.xml"/>
<xi:include href="config:///core/en/strings.xml"/>
<xi:include href="config:///core/common/items.xml"/>
<xi:include href="config:///core/common/herbs.xml" />
<xi:include href="config:///core/spoils.xml"/>
<xi:include href="config:///core/prefixes.xml"/>
<xi:include href="config:///core/common/buildings.xml"/>
<xi:include href="config:///game/familiars.xml"/>
<xi:include href="config:///game/ships.xml"/>
<xi:include href="config:///game/shipnames.xml"/>
<xi:include href="config:///game/terrains.xml"/>
<xi:include href="config:///core/calendar.xml"/>
<xi:include href="config:///game/items.xml" />
<xi:include href="config:///game/strings.xml"/>
<xi:include href="config:///game/messages.xml"/>
<xi:include href="config:///game/races.xml"/>
<xi:include href="config:///game/buildings.xml"/>
<xi:include href="config:///game/equipment.xml"/>
<xi:include href="config:///game/spells.xml"/>
<xi:include href="config:///game/luxuries.xml" />
<xi:include href="config:///game/weapons.xml" />
<xi:include href="config:///game/armor.xml" />
<xi:include href="config:///game/resources.xml" />
<calendar name="thirdage" newyear="month_1" start="1"/>
<equipment>
<set name="first_unit">
<item name="conquesttoken" amount="1"/>
<item name="log" amount="10"/>
<item name="stone" amount="10"/>
<item name="money" amount="5000"/>
</set>
</equipment>
<xi:include href="config:///default/names-undead.xml"/>
<xi:include href="config:///default/names-skeletons.xml"/>
<xi:include href="config:///default/names-zombies.xml"/>
<xi:include href="config:///default/names-ghouls.xml"/>
<xi:include href="config:///default/names-dragons.xml"/>
<game name="E4">
<!-- Game specific settings -->
<param name="database.gameid" value="7"></param>
<order name="BELAGERE" disable="yes"/>
<order name="BEKLAUEN" disable="yes"/>
<order name="GM" disable="yes"/>
<order name="KAUFEN" disable="yes"/>
<order name="LEHREN" disable="yes"/>
<order name="SABOTIEREN" disable="yes"/>
<order name="SPIONIEREN" disable="yes"/>
<order name="TREIBEN" disable="yes"/>
<order name="UNTERHALTEN" disable="yes"/>
<order name="VERKAUFEN" disable="yes"/>
<skill name="armorer" enable="true"/>
<skill name="bow" enable="true"/>
<skill name="building" enable="true"/>
<skill name="cartmaking" enable="true"/>
<skill name="catapult" enable="true"/>
<skill name="crossbow" enable="true"/>
<skill name="forestry" enable="true"/>
<skill name="magic" enable="true"/>
<skill name="melee" enable="true"/>
<skill name="mining" enable="true"/>
<skill name="polearm" enable="true"/>
<skill name="quarrying" enable="true"/>
<skill name="riding" enable="true"/>
<skill name="roadwork" enable="true"/>
<skill name="sailing" enable="true"/>
<skill name="shipcraft" enable="true"/>
<skill name="stamina" enable="true"/>
<skill name="tactics" enable="true"/>
<skill name="training" enable="true"/>
<skill name="unarmed" enable="true"/>
<skill name="weaponsmithing" enable="true"/>
<skill name="herbalism" enable="false"/>
<skill name="alchemy" enable="false"/>
<skill name="entertainment" enable="false"/>
<skill name="espionage" enable="false"/>
<skill name="perception" enable="false"/>
<skill name="stealth" enable="false"/>
<skill name="taxation" enable="false"/>
<skill name="trade" enable="false"/>
<param name="NewbieImmunity" value="9"/> <!-- ends after turn 9 -->
<param name="modules.astralspace" value="0"/>
<param name="modules.wormholes" value="0"/>
<param name="modules.markets" value="1"/>
<!-- resource limitations -->
<param name="magic.regeneration" value="0.75"/>
<param name="magic.power" value="0.5"/>
<param name="resource.factor" value="0.25"/>
<param name="skills.cost.tactics" value="500"/>
<param name="entertain.base" value="0"/>
<param name="entertain.perlevel" value="20"/>
<param name="nmr.timeout" value="5"/>
<param name="nmr.removenewbie" value="0"/>
<param name="GiveRestriction" value="3"/>
<param name="hunger.long" value="0"/>
<param name="hunger.demon.skill" value="1"/>
<param name="hunger.damage" value="1d9+9"/>
<param name="hunger.demons" value="1"/>
<param name="init_spells" value="0"/>
<param name="recruit.allow_merge" value="1"/>
<param name="study.expensivemigrants" value="1"/>
<param name="study.speedup" value="0"/>
<param name="world.era" value="3"/>
<param name="rules.migrants" value="0"/>
<param name="rules.transfermen" value="0"/>
<param name="rules.stealth.faction" value="1"/>
<param name="rules.stealth.anon_battle" value="0"/>
<param name="rules.check_overload" value="0"/>
<param name="rules.combat.goblinbonus" value="3"/>
<param name="rules.ship.damage_drift" value="0.00"/> <!-- percent damage from drifting-->
<param name="rules.alliances" value="1"/>
<param name="rules.combat.herospeed" value="3"/>
<param name="rules.combat.demon_vampire" value="5"/> <!-- regen 1 hp per X points of damage done -->
<param name="rules.combat.nat_armor" value="1"/>
<param name="rules.combat.skill_bonus" value="0"/>
<!--param name="rules.combat.loot" value="5"/--> <!-- only self + others - keeploot -->
<param name="rules.items.loot_divisor" value="2"/> <!-- damage skims off 1/2 of goods transfers -->
<param name="rules.items.give_divisor" value="2"/> <!-- corruption skims off 1/2 of goods transfers -->
<param name="rules.move.owner_leave" value="1"/> <!-- owner must leave before moving -->
<param name="rules.region_owners" value="1"/>
<param name="rules.cavalry.skill" value="2"/>
<param name="rules.cavalry.mode" value="1"/>
<param name="rules.magic.multipotion" value="1"/>
<param name="rules.magic.wol_effect" value="5"/>
<param name="rules.magic.factionlist" value="1"/>
<param name="rules.magic.wol_type" value="2"/>
<param name="rules.magic.blessed_harvest" value="1"/>
<param name="rules.magic.elfpower" value="1"/> <!-- elves get ring-of-power bonus in a forest -->
<param name="rules.magic.playerschools" value="gwyrrd illaun draig cerddor"/>
<param name="rules.build.other_buildings" value="1"/>
<param name="rules.economy.taxation" value="1"/>
<param name="rules.economy.food" value="2"/>
<param name="rules.economy.wages" value="1"/>
<param name="rules.economy.roqf" value="5"/>
<param name="rules.economy.herbrot" value="0"/>
<param name="rules.dwarf_castles" value="1"/>
<!-- param name="rules.nmr.destroy" value="1"/ -->
<param name="rules.limit.faction" value="250"/>
<!--param name="rules.give" value="15"/ --> <!-- self + peasants + herbs + lux - goods -->
<param name="rules.economy.grow" value="1"/>
<param name="rules.tactics.formula" value="1"/> <!-- 10% per skilldiff -->
<param name="rules.help.mask" value="fight guard money give"/>
<param name="movement.shipspeed.skillbonus" value="6"/>
<param name="alliance.auto" value="fight"/>
<param name="alliance.restricted" value="fight"/>
</game>
<rules>
<function name="wage" value="minimum_wage"/>
</rules>
<strings>
<string name="mailto">
<text locale="de">eressea-server@eressea.de</text>
<text locale="en">eressea-server@eressea.de</text>
</string>
<string name="newbie_info_1">
<text locale="de">Bitte denke daran, deine Befehle mit dem Betreff
ERESSEA 4 BEFEHLE an eressea-server@eressea.de zu senden.</text>
<text locale="en">Remember to send your orders to
eressea-server@eressea.de with the subject ERESSEA 4 ORDERS.</text>
</string>
<string name="mailcmd">
<text locale="de">ERESSEA 4 BEFEHLE</text>
<text locale="en">ERESSEA 4 ORDERS</text>
</string>
</strings>
</eressea>

View file

@ -1,16 +0,0 @@
[eressea]
base = .
report = reports
verbose = 0
lomem = 0
debug = 0
memcheck = 0
locales = de,en
[config]
rules = e3a
source_dir = ..
maxnmrs = 20
[editor]
color = 1

View file

@ -1,2 +0,0 @@
require "setup"
run_tests()

View file

@ -1,14 +0,0 @@
local srcpath = config.source_dir
local respath = srcpath .. '/res'
local paths = {
'scripts/?.lua',
'core/scripts/?.lua',
'lunit/?.lua'
}
for idx, path in pairs(paths) do
package.path = srcpath .. '/' .. path .. ';' .. package.path
end
assert(read_xml())
require "init"

31
process/cron/backup-eressea Executable file
View file

@ -0,0 +1,31 @@
#!/bin/bash
if [ -z $ERESSEA ] ; then
ERESSEA=$HOME/eressea
echo "The ERESSEA environment variable is not set. Assuming $ERESSEA."
fi
GAME=$1
if [ ! -d $ERESSEA/game-$GAME ]; then
echo "No such game: game-$GAME."
exit 1
fi
cd $ERESSEA/game-$GAME
TURN=$2
if [ -z $TURN ]; then
TURN=$(cat turn)
fi
if [ ! -e data/$TURN.dat ]; then
echo "No data for turn $TURN in game $GAME."
exit 2
fi
if [ ! -d backup ] ; then
echo "creating missing backup directory for game $GAME."
mkdir -p ~/backup/eressea/game-$GAME
ln -sf ~/backup/eressea/game-$GAME backup
fi
files="data/$TURN.dat parteien.full parteien"
if [ -e orders.$TURN ]; then
files="$files orders.$TURN"
fi
echo "backup turn $TURN, game $GAME, files: $files"
tar cjf backup/$TURN.tar.bz2 $files

16
process/cron/create-orders Executable file
View file

@ -0,0 +1,16 @@
GAME=$1
TURN=$2
if [ ! -d $ERESSEA/game-$GAME ] ; then
echo "No such game: $GAME"
exit 1
fi
cd $ERESSEA/game-$GAME
if [ -d orders.dir.$TURN ]; then
echo "orders.dir.$TURN already exists"
else
mv orders.dir orders.dir.$TURN
mkdir -p orders.dir
fi
ls -1rt orders.dir.$TURN/turn-* | xargs cat > orders.$TURN

View file

@ -12,14 +12,15 @@ if [ -d $REPORTS ]; then
rm -rf $REPORTS rm -rf $REPORTS
fi fi
mkdir $REPORTS mkdir $REPORTS
$BIN/backup-eressea $GAME $TURN
cd $ERESSEA/game-$GAME cd $ERESSEA/game-$GAME
if [ -d test ]; then if [ -d test ]; then
touch test/execute.lock touch test/execute.lock
fi fi
$BIN/create-orders $GAME $TURN
$BIN/backup-eressea $GAME $TURN
rm -f execute.lock rm -f execute.lock
$BIN/run-turn $GAME $BIN/run-turn $GAME $TURN
touch execute.lock touch execute.lock
if [ ! -s $ERESSEA/game-$GAME/orders.$TURN ]; then if [ ! -s $ERESSEA/game-$GAME/orders.$TURN ]; then

14
process/cron/run-turn Executable file
View file

@ -0,0 +1,14 @@
GAME=$1
TURN=$2
if [ ! -d $ERESSEA/game-$GAME ] ; then
echo "No such game: $GAME"
exit 1
fi
cd $ERESSEA/game-$GAME
echo "running turn $TURN, game $GAME"
$ERESSEA/server/bin/eressea -v1 -t $TURN run-turn.lua
mkdir -p log
ln -f eressea.log log/eressea.log.$TURN

View file

@ -1,24 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1"> <building name="castle" capacity="1">
<function name="name" value="castle_name_2"/> <function name="name" value="castle_name_2"/>
<function name="protection" value="lua_building_protection"/> <function name="protection" value="building_protection"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="10" reqsize="1"> <construction skill="building" minskill="1" maxsize="10" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40" reqsize="1"> <construction skill="building" minskill="2" maxsize="40" reqsize="1" defense_bonus="1">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200" reqsize="1"> <construction skill="building" minskill="3" maxsize="200" reqsize="1" defense_bonus="3">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000" reqsize="1"> <construction skill="building" minskill="4" maxsize="1000" reqsize="1" defense_bonus="5">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000" reqsize="1"> <construction skill="building" minskill="5" maxsize="5000" reqsize="1" defense_bonus="8">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6" reqsize="1"> <construction skill="building" minskill="6" reqsize="1" defense_bonus="12">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View file

@ -1,26 +1,26 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<building name="castle" capacity="1"> <building name="castle" capacity="1">
<function name="name" value="castle_name"/> <function name="name" value="castle_name"/>
<function name="protection" value="eressea_building_protection"/> <function name="protection" value="building_protection"/>
<construction skill="building" minskill="1" maxsize="2" reqsize="1"> <construction skill="building" minskill="1" maxsize="2" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="1" maxsize="8" reqsize="1"> <construction skill="building" minskill="1" maxsize="8" reqsize="1" defense_bonus="0">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="40" reqsize="1"> <construction skill="building" minskill="2" maxsize="40" reqsize="1" defense_bonus="1">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="3" maxsize="200" reqsize="1"> <construction skill="building" minskill="3" maxsize="200" reqsize="1" defense_bonus="3">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="4" maxsize="1000" reqsize="1"> <construction skill="building" minskill="4" maxsize="1000" reqsize="1" defense_bonus="5">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="5" maxsize="5000" reqsize="1"> <construction skill="building" minskill="5" maxsize="5000" reqsize="1" defense_bonus="8">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="6" reqsize="1"> <construction skill="building" minskill="6" reqsize="1" defense_bonus="12">
<requirement type="stone" quantity="1"/> <requirement type="stone" quantity="1"/>
</construction> </construction>
</building> </building>

View file

@ -1,6 +1,10 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<resources> <resources>
<resource name="money">
<item weight="0"/>
</resource>
<resource name="ao_healing" appearance="amulet"> <resource name="ao_healing" appearance="amulet">
<item weight="0" score="6000"/> <item weight="0" score="6000"/>
</resource> </resource>

View file

@ -1,5 +1,23 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<messages> <messages>
<message name="force_leave_ship" section="events">
<type>
<arg name="unit" type="unit"/>
<arg name="owner" type="unit"/>
<arg name="ship" type="ship"/>
</type>
<text locale="de">$unit($owner) bittet $unit($unit), $ship($ship) zu verlassen.</text>
<text locale="en">$unit($owner) asks $unit($unit) to leave $ship($ship).</text>
</message>
<message name="force_leave_building" section="events">
<type>
<arg name="unit" type="unit"/>
<arg name="owner" type="unit"/>
<arg name="building" type="building"/>
</type>
<text locale="de">$unit($owner) bittet $unit($unit), $building($building) zu verlassen.</text>
<text locale="en">$unit($owner) asks $unit($unit) to leave $building($building).</text>
</message>
<message name="alp_destroyed" section="events"> <message name="alp_destroyed" section="events">
<type> <type>
<arg name="region" type="region"/> <arg name="region" type="region"/>

View file

@ -5,15 +5,15 @@
<building name="watch" capacity="1" maxsize="10"> <building name="watch" capacity="1" maxsize="10">
<function name="name" value="fort_name"/> <function name="name" value="fort_name"/>
<function name="protection" value="lua_building_protection"/> <function name="protection" value="building_protection"/>
<function name="taxes" value="lua_building_taxes"/> <function name="taxes" value="lua_building_taxes"/>
<construction skill="building" minskill="1" maxsize="5" reqsize="1"> <construction skill="building" minskill="1" maxsize="5" reqsize="1" defense_bonus="0">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" maxsize="5" reqsize="1"> <construction skill="building" minskill="2" maxsize="5" reqsize="1" defense_bonus="1">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
<construction skill="building" minskill="2" reqsize="1"> <construction skill="building" minskill="2" reqsize="1" defense_bonus="2">
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
</construction> </construction>
</building> </building>

View file

@ -26,10 +26,6 @@ function item_canuse(u, iname)
return true return true
end end
function building_protection(b, u)
return 1
end
function building_taxes(b, blevel) function building_taxes(b, blevel)
btype = b.type btype = b.type
if btype=="castle" then if btype=="castle" then

View file

@ -712,6 +712,42 @@ function test_golem_use_four_iron()
assert_equal(4, u1:get_item("towershield")) assert_equal(4, u1:get_item("towershield"))
end end
function skip_test_silver_weight_stops_movement()
local r1 = region.create(1, 1, "plain")
local r2 = region.create(2, 1, "plain")
region.create(3, 1, "plain")
local f1 = faction.create("noreply@eressea.de", "human", "de")
local u1 = unit.create(f1, r1, 1)
u1:clear_orders()
u1:add_order("NACH OST")
u1:add_item("money", 540)
assert_equal(1540, u1.weight)
process_orders()
assert_equal(r2, u1.region)
u1:add_item("money", 1)
process_orders()
assert_equal(r2, u1.region)
end
function skip_test_silver_weight_stops_ship()
local r1 = region.create(1, 1, "ocean")
local r2 = region.create(2, 1, "ocean")
region.create(3, 1, "ocean")
local f1 = faction.create("noreply@eressea.de", "human", "de")
local u1 = unit.create(f1, r1, 1)
u1:set_skill("sailing", 3)
local s1 = ship.create(r1, "canoe")
u1.ship = s1
u1:clear_orders()
u1:add_order("NACH OST")
u1:add_item("money", 2000)
process_orders()
assert_equal(r2, u1.region)
u1:add_item("money", 1)
process_orders()
assert_equal(r2, u1.region)
end
function test_building_owner_can_enter_ship() function test_building_owner_can_enter_ship()
local r1 = region.create(1, 2, "plain") local r1 = region.create(1, 2, "plain")
local f1 = faction.create("noreply@eressea.de", "human", "de") local f1 = faction.create("noreply@eressea.de", "human", "de")
@ -734,3 +770,12 @@ function test_building_owner_can_enter_ship()
assert_equal(s1, u1.ship) assert_equal(s1, u1.ship)
assert_equal(null, u1.building, "owner of the building can not go into a ship") assert_equal(null, u1.building, "owner of the building can not go into a ship")
end end
function test_weightless_silver()
local r1 = region.create(1, 2, "plain")
local f1 = faction.create("noreply@eressea.de", "human", "de")
local u1 = unit.create(f1, r1, 1)
assert_equal(1000, u1.weight)
u1:add_item("money", 540)
assert_equal(1000, u1.weight)
end

View file

@ -126,25 +126,27 @@ set(SERVER_SRC
bind_ship.c bind_ship.c
bind_storage.c bind_storage.c
bind_unit.c bind_unit.c
${ERESSEA_SRC}) )
if (SQLITE3_FOUND) if (SQLITE3_FOUND)
set (SERVER_SRC set (SERVER_SRC ${SERVER_SRC}
sqlite.c sqlite.c
bind_sqlite.c bind_sqlite.c
${SERVER_SRC}) )
endif (SQLITE3_FOUND) endif (SQLITE3_FOUND)
if (CURSES_FOUND) if (CURSES_FOUND)
set (SERVER_SRC set (SERVER_SRC ${SERVER_SRC}
gmtool.c gmtool.c
listbox.c listbox.c
bind_gmtool.c bind_gmtool.c
${SERVER_SRC}) )
endif(CURSES_FOUND) endif(CURSES_FOUND)
add_library(game ${ERESSEA_SRC})
add_executable(eressea ${SERVER_SRC}) add_executable(eressea ${SERVER_SRC})
target_link_libraries(eressea target_link_libraries(eressea
game
${TOLUA_LIBRARIES} ${TOLUA_LIBRARIES}
${LUA_LIBRARIES} ${LUA_LIBRARIES}
${QUICKLIST_LIBRARIES} ${QUICKLIST_LIBRARIES}
@ -178,12 +180,12 @@ set(TESTS_SRC
${ATTRIBUTES_TESTS} ${ATTRIBUTES_TESTS}
${UTIL_TESTS} ${UTIL_TESTS}
${KERNEL_TESTS} ${KERNEL_TESTS}
${ERESSEA_SRC}
) )
add_executable(test_eressea ${TESTS_SRC}) add_executable(test_eressea ${TESTS_SRC})
target_link_libraries(test_eressea ${CUTEST_LIBRARIES})
target_link_libraries(test_eressea target_link_libraries(test_eressea
game
${CUTEST_LIBRARIES}
${LUA_LIBRARIES} ${LUA_LIBRARIES}
${QUICKLIST_LIBRARIES} ${QUICKLIST_LIBRARIES}
${STORAGE_LIBRARIES} ${STORAGE_LIBRARIES}

View file

@ -1,4 +1,3 @@
#include <config.h>
#include <platform.h> #include <platform.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <kernel/region.h> #include <kernel/region.h>

View file

@ -1901,7 +1901,7 @@ int skilldiff(troop at, troop dt, int dist)
init = true; init = true;
} }
if (df->building->type->protection) { if (df->building->type->protection) {
int beff = df->building->type->protection(df->building, du); int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS);
if (beff) { if (beff) {
skdiff -= beff; skdiff -= beff;
is_protected = 2; is_protected = 2;
@ -1918,7 +1918,7 @@ int skilldiff(troop at, troop dt, int dist)
if (magicwalls_ct if (magicwalls_ct
&& curse_active(get_curse(df->building->attribs, magicwalls_ct))) { && curse_active(get_curse(df->building->attribs, magicwalls_ct))) {
/* Verdoppelt Burgenbonus */ /* Verdoppelt Burgenbonus */
skdiff -= buildingeffsize(df->building, false); skdiff -= df->building->type->protection(df->building, du, DEFENSE_BONUS);
} }
} }
/* Goblin-Verteidigung /* Goblin-Verteidigung

View file

@ -9,6 +9,7 @@
#include <kernel/race.h> #include <kernel/race.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <util/functions.h>
#include <CuTest.h> #include <CuTest.h>
#include "tests.h" #include "tests.h"
@ -26,7 +27,7 @@ static void test_make_fighter(CuTest * tc)
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
f = test_create_faction(rc_find("human")); f = test_create_faction(NULL);
au = test_create_unit(f, r); au = test_create_unit(f, r);
enable_skill(SK_MAGIC, true); enable_skill(SK_MAGIC, true);
enable_skill(SK_RIDING, true); enable_skill(SK_RIDING, true);
@ -57,131 +58,160 @@ static void test_make_fighter(CuTest * tc)
test_cleanup(); test_cleanup();
} }
static int add_two(building * b, unit * u) { static int add_two(building * b, unit * u, building_bonus bonus) {
return 2; return 2;
} }
static void test_defenders_get_building_bonus(CuTest * tc) static void test_defenders_get_building_bonus(CuTest * tc)
{ {
unit *du, *au; unit *du, *au;
region *r; region *r;
building * bld; building * bld;
fighter *df, *af; fighter *df, *af;
battle *b; battle *b;
side *ds, *as; side *ds, *as;
int diff; int diff;
troop dt, at; troop dt, at;
building_type * btype; building_type * btype;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
du = test_create_unit(test_create_faction(rc_find("human")), r); du = test_create_unit(test_create_faction(NULL), r);
au = test_create_unit(test_create_faction(rc_find("human")), r); au = test_create_unit(test_create_faction(NULL), r);
u_set_building(du, bld); u_set_building(du, bld);
b = make_battle(r); b = make_battle(r);
ds = make_side(b, du->faction, 0, 0, 0); ds = make_side(b, du->faction, 0, 0, 0);
df = make_fighter(b, du, ds, false); df = make_fighter(b, du, ds, false);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, true); af = make_fighter(b, au, as, true);
CuAssertPtrEquals(tc, bld, df->building); CuAssertPtrEquals(tc, bld, df->building);
CuAssertPtrEquals(tc, 0, af->building); CuAssertPtrEquals(tc, 0, af->building);
dt.fighter = df; dt.fighter = df;
dt.index = 0; dt.index = 0;
at.fighter = af; at.fighter = af;
at.index = 0; at.index = 0;
diff = skilldiff(at, dt, 0); diff = skilldiff(at, dt, 0);
CuAssertIntEquals(tc, -2, diff); CuAssertIntEquals(tc, -2, diff);
diff = skilldiff(dt, at, 0); diff = skilldiff(dt, at, 0);
CuAssertIntEquals(tc, 0, diff); CuAssertIntEquals(tc, 0, diff);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_attackers_get_no_building_bonus(CuTest * tc) static void test_attackers_get_no_building_bonus(CuTest * tc)
{ {
unit *au; unit *au;
region *r; region *r;
building * bld; building * bld;
fighter *af; fighter *af;
battle *b; battle *b;
side *as; side *as;
building_type * btype; building_type * btype;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
au = test_create_unit(test_create_faction(rc_find("human")), r); au = test_create_unit(test_create_faction(NULL), r);
u_set_building(au, bld); u_set_building(au, bld);
b = make_battle(r); b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, true); af = make_fighter(b, au, as, true);
CuAssertPtrEquals(tc, 0, af->building); CuAssertPtrEquals(tc, 0, af->building);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_building_bonus_respects_size(CuTest * tc) static void test_building_bonus_respects_size(CuTest * tc)
{ {
unit *au, *du; unit *au, *du;
region *r; region *r;
building * bld; building * bld;
fighter *af, *df; fighter *af, *df;
battle *b; battle *b;
side *as; side *as;
building_type * btype; building_type * btype;
faction * f; faction * f;
test_cleanup(); test_cleanup();
test_create_world(); test_create_world();
r = findregion(0, 0); r = findregion(0, 0);
btype = bt_get_or_create("castle"); btype = bt_get_or_create("castle");
btype->protection = &add_two; btype->protection = &add_two;
bld = test_create_building(r, btype); bld = test_create_building(r, btype);
bld->size = 10; bld->size = 10;
f = test_create_faction(rc_find("human")); f = test_create_faction(NULL);
au = test_create_unit(f, r); au = test_create_unit(f, r);
scale_number(au, 9); scale_number(au, 9);
u_set_building(au, bld); u_set_building(au, bld);
du = test_create_unit(f, r); du = test_create_unit(f, r);
u_set_building(du, bld); u_set_building(du, bld);
scale_number(du, 2); scale_number(du, 2);
b = make_battle(r); b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0); as = make_side(b, au->faction, 0, 0, 0);
af = make_fighter(b, au, as, false); af = make_fighter(b, au, as, false);
df = make_fighter(b, du, as, false); df = make_fighter(b, du, as, false);
CuAssertPtrEquals(tc, bld, af->building); CuAssertPtrEquals(tc, bld, af->building);
CuAssertPtrEquals(tc, 0, df->building); CuAssertPtrEquals(tc, 0, df->building);
free_battle(b); free_battle(b);
test_cleanup(); test_cleanup();
} }
static void test_building_defence_bonus(CuTest * tc)
{
unit *au;
region *r;
building * bld;
building_type * btype;
faction * f;
int def;
test_cleanup();
test_create_world();
r = findregion(0, 0);
register_buildings();
btype = bt_get_or_create("castle");
btype->protection = (int (*)(struct building *, struct unit *, building_bonus))get_function("building_protection");
btype->construction->defense_bonus = 3;
bld = test_create_building(r, btype);
bld->size = 1;
f = test_create_faction(NULL);
au = test_create_unit(f, r);
scale_number(au, 1);
u_set_building(au, bld);
def = btype->protection(bld, au, DEFENSE_BONUS);
CuAssertIntEquals(tc, 3, def);
test_cleanup();
}
CuSuite *get_battle_suite(void) CuSuite *get_battle_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_make_fighter); SUITE_ADD_TEST(suite, test_make_fighter);
SUITE_ADD_TEST(suite, test_defenders_get_building_bonus); SUITE_ADD_TEST(suite, test_defenders_get_building_bonus);
SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus); SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus);
SUITE_ADD_TEST(suite, test_building_bonus_respects_size); SUITE_ADD_TEST(suite, test_building_bonus_respects_size);
return suite; SUITE_ADD_TEST(suite, test_building_defence_bonus);
return suite;
} }

View file

@ -32,6 +32,7 @@ int config_parse(const char *json)
if (conf) { if (conf) {
json_config(conf); json_config(conf);
cJSON_Delete(conf); cJSON_Delete(conf);
init_locales();
return 0; return 0;
} else { } else {
int line; int line;

View file

@ -1,3 +1,4 @@
#include <platform.h>
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4100) #pragma warning(disable: 4100)
#include "config.pkg.c" #include "config.pkg.c"

View file

@ -193,7 +193,7 @@ static int tolua_translate(lua_State * L)
const char *lang = tolua_tostring(L, 2, 0); const char *lang = tolua_tostring(L, 2, 0);
struct locale *loc = lang ? get_locale(lang) : default_locale; struct locale *loc = lang ? get_locale(lang) : default_locale;
if (loc) { if (loc) {
str = locale_string(loc, str); str = LOC(loc, str);
tolua_pushstring(L, str); tolua_pushstring(L, str);
return 1; return 1;
} }

View file

@ -1,3 +1,3 @@
#define VERSION_MAJOR 3 #define VERSION_MAJOR 3
#define VERSION_MINOR 4 #define VERSION_MINOR 5
#define VERSION_BUILD 695 #define VERSION_BUILD 697

View file

@ -1,4 +1,3 @@
#include <config.h>
#include <platform.h> #include <platform.h>
#include "callback.h" #include "callback.h"
#include <stdlib.h> #include <stdlib.h>

View file

@ -92,7 +92,7 @@ static const char *crtag(const char *key)
static const struct locale *lang = NULL; static const struct locale *lang = NULL;
if (!lang) if (!lang)
lang = get_locale(TAG_LOCALE); lang = get_locale(TAG_LOCALE);
return locale_string(lang, key); return LOC(lang, key);
} }
#else #else
#define crtag(x) (x) #define crtag(x) (x)
@ -274,7 +274,7 @@ cr_output_curses(FILE * F, const faction * viewer, const void *obj, objtype_t ty
fputs("EFFECTS\n", F); fputs("EFFECTS\n", F);
} }
fprintf(F, "\"%d %s\"\n", data->value, translate(key, fprintf(F, "\"%d %s\"\n", data->value, translate(key,
locale_string(default_locale, key))); LOC(default_locale, key)));
} }
} }
a = a->next; a = a->next;
@ -331,7 +331,7 @@ static int cr_resource(variant var, char *buffer, const void *userdata)
if (r) { if (r) {
const char *key = resourcename(r, 0); const char *key = resourcename(r, 0);
sprintf(buffer, "\"%s\"", sprintf(buffer, "\"%s\"",
translate(key, locale_string(report->locale, key))); translate(key, LOC(report->locale, key)));
return 0; return 0;
} }
return -1; return -1;
@ -343,7 +343,7 @@ static int cr_race(variant var, char *buffer, const void *userdata)
const struct race *rc = (const race *)var.v; const struct race *rc = (const race *)var.v;
const char *key = rc_name_s(rc, NAME_SINGULAR); const char *key = rc_name_s(rc, NAME_SINGULAR);
sprintf(buffer, "\"%s\"", sprintf(buffer, "\"%s\"",
translate(key, locale_string(report->locale, key))); translate(key, LOC(report->locale, key)));
return 0; return 0;
} }
@ -649,7 +649,7 @@ const faction * f, const region * r)
if (sh->display && sh->display[0]) if (sh->display && sh->display[0])
fprintf(F, "\"%s\";Beschr\n", sh->display); fprintf(F, "\"%s\";Beschr\n", sh->display);
fprintf(F, "\"%s\";Typ\n", translate(sh->type->_name, fprintf(F, "\"%s\";Typ\n", translate(sh->type->_name,
locale_string(f->locale, sh->type->_name))); LOC(f->locale, sh->type->_name)));
fprintf(F, "%d;Groesse\n", sh->size); fprintf(F, "%d;Groesse\n", sh->size);
if (sh->damage) { if (sh->damage) {
int percent = int percent =
@ -839,20 +839,20 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) {
const char *zRace = rc_name_s(u_race(u), NAME_PLURAL); const char *zRace = rc_name_s(u_race(u), NAME_PLURAL);
fprintf(F, "\"%s\";wahrerTyp\n", fprintf(F, "\"%s\";wahrerTyp\n",
translate(zRace, locale_string(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
} }
} }
else { else {
const race *irace = u_irace(u); const race *irace = u_irace(u);
const char *zRace = rc_name_s(irace, NAME_PLURAL); const char *zRace = rc_name_s(irace, NAME_PLURAL);
fprintf(F, "\"%s\";Typ\n", fprintf(F, "\"%s\";Typ\n",
translate(zRace, locale_string(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
if (u->faction == f && irace != u_race(u)) { if (u->faction == f && irace != u_race(u)) {
assert(skill_enabled(SK_STEALTH) assert(skill_enabled(SK_STEALTH)
|| !"we're resetting this on load, so.. ircase should never be used"); || !"we're resetting this on load, so.. ircase should never be used");
zRace = rc_name_s(u_race(u), NAME_PLURAL); zRace = rc_name_s(u_race(u), NAME_PLURAL);
fprintf(F, "\"%s\";wahrerTyp\n", fprintf(F, "\"%s\";wahrerTyp\n",
translate(zRace, locale_string(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
} }
} }
@ -902,7 +902,7 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
c = hp_status(u); c = hp_status(u);
if (c && *c && (u->faction == f || omniscient(f))) { if (c && *c && (u->faction == f || omniscient(f))) {
fprintf(F, "\"%s\";hp\n", translate(c, fprintf(F, "\"%s\";hp\n", translate(c,
locale_string(u->faction->locale, c))); LOC(u->faction->locale, c)));
} }
if (fval(u, UFL_HERO)) { if (fval(u, UFL_HERO)) {
fputs("1;hero\n", F); fputs("1;hero\n", F);
@ -998,8 +998,7 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
pr = 1; pr = 1;
fputs("GEGENSTAENDE\n", F); fputs("GEGENSTAENDE\n", F);
} }
fprintf(F, "%d;%s\n", in, translate(ic, locale_string(f->locale, fprintf(F, "%d;%s\n", in, translate(ic, LOC(f->locale, ic)));
ic)));
} }
cr_output_curses(F, f, u, TYP_UNIT); cr_output_curses(F, f, u, TYP_UNIT);
@ -1294,8 +1293,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
} }
tname = terrain_name(r); tname = terrain_name(r);
fprintf(F, "\"%s\";Terrain\n", translate(tname, locale_string(f->locale, fprintf(F, "\"%s\";Terrain\n", translate(tname, LOC(f->locale, tname)));
tname)));
if (sr->mode != see_unit) if (sr->mode != see_unit)
fprintf(F, "\"%s\";visibility\n", visibility[sr->mode]); fprintf(F, "\"%s\";visibility\n", visibility[sr->mode]);
if (sr->mode == see_neighbour) { if (sr->mode == see_neighbour) {
@ -1359,12 +1357,12 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
if (lux) { if (lux) {
const char *ch = resourcename(lux->rtype, 0); const char *ch = resourcename(lux->rtype, 0);
fprintf(F, "%d;%s\n", 1, translate(ch, fprintf(F, "%d;%s\n", 1, translate(ch,
locale_string(f->locale, ch))); LOC(f->locale, ch)));
} }
if (herb) { if (herb) {
const char *ch = resourcename(herb->rtype, 0); const char *ch = resourcename(herb->rtype, 0);
fprintf(F, "%d;%s\n", 1, translate(ch, fprintf(F, "%d;%s\n", 1, translate(ch,
locale_string(f->locale, ch))); LOC(f->locale, ch)));
} }
} }
} }
@ -1376,7 +1374,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
fprintf(F, "%d;%s\n", (dmd->value fprintf(F, "%d;%s\n", (dmd->value
? dmd->value * dmd->type->price ? dmd->value * dmd->type->price
: -dmd->type->price), : -dmd->type->price),
translate(ch, locale_string(f->locale, ch))); translate(ch, LOC(f->locale, ch)));
dmd = dmd->next; dmd = dmd->next;
} }
} }
@ -1491,7 +1489,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset)
faction *f = ctx->f; faction *f = ctx->f;
const char *prefix; const char *prefix;
region *r; region *r;
const char *mailto = locale_string(f->locale, "mailto"); const char *mailto = LOC(f->locale, "mailto");
const attrib *a; const attrib *a;
seen_region *sr = NULL; seen_region *sr = NULL;
#if SCORE_MODULE #if SCORE_MODULE
@ -1530,7 +1528,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset)
fprintf(F, "%d.%d.%d;Build\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); fprintf(F, "%d.%d.%d;Build\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
if (mailto != NULL) { if (mailto != NULL) {
fprintf(F, "\"%s\";mailto\n", mailto); fprintf(F, "\"%s\";mailto\n", mailto);
fprintf(F, "\"%s\";mailcmd\n", locale_string(f->locale, "mailcmd")); fprintf(F, "\"%s\";mailcmd\n", LOC(f->locale, "mailcmd"));
} }
show_alliances_cr(F, f); show_alliances_cr(F, f);
@ -1651,8 +1649,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset)
continue; continue;
ch = resourcename(ptype->itype->rtype, 0); ch = resourcename(ptype->itype->rtype, 0);
fprintf(F, "TRANK %d\n", hashstring(ch)); fprintf(F, "TRANK %d\n", hashstring(ch));
fprintf(F, "\"%s\";Name\n", translate(ch, locale_string(f->locale, fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch)));
ch)));
fprintf(F, "%d;Stufe\n", ptype->level); fprintf(F, "%d;Stufe\n", ptype->level);
if (description == NULL) { if (description == NULL) {
@ -1669,8 +1666,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset)
while (m->number) { while (m->number) {
ch = resourcename(m->rtype, 0); ch = resourcename(m->rtype, 0);
fprintf(F, "\"%s\"\n", translate(ch, locale_string(f->locale, fprintf(F, "\"%s\"\n", translate(ch, LOC(f->locale, ch)));
ch)));
m++; m++;
} }
} }

View file

@ -43,7 +43,7 @@ void init_directions(struct locale *lang) {
register_special_direction(lang, "vortex"); register_special_direction(lang, "vortex");
for (i = 0; dirs[i].direction != NODIRECTION; ++i) { for (i = 0; dirs[i].direction != NODIRECTION; ++i) {
const char *str = locale_string(lang, dirs[i].name); const char *str = locale_string(lang, dirs[i].name, false);
if (str) { if (str) {
variant token; variant token;
token.i = dirs[i].direction; token.i = dirs[i].direction;

View file

@ -20,12 +20,14 @@
#include <modules/xmas.h> #include <modules/xmas.h>
#include <items/itemtypes.h> #include <items/itemtypes.h>
#include <attributes/attributes.h> #include <attributes/attributes.h>
#include <races/races.h>
#include "chaos.h" #include "chaos.h"
#include "report.h" #include "report.h"
#include "items.h" #include "items.h"
#include "creport.h" #include "creport.h"
#include "names.h" #include "names.h"
#include "wormhole.h" #include "wormhole.h"
#include "spells.h"
void game_done(void) void game_done(void)
{ {
@ -55,6 +57,8 @@ void game_init(void)
register_nr(); register_nr();
register_cr(); register_cr();
register_races();
register_spells();
register_names(); register_names();
register_resources(); register_resources();
register_buildings(); register_buildings();

View file

@ -106,7 +106,7 @@ static void test_give_men_none(CuTest * tc) {
env.f2 = env.f1 = test_create_faction(0); env.f2 = env.f1 = test_create_faction(0);
setup_give(&env); setup_give(&env);
msg = give_men(0, env.src, env.dst, NULL); msg = give_men(0, env.src, env.dst, NULL);
CuAssertStrEquals(tc, "error96", (const char *)msg->parameters[3].v); CuAssertStrEquals(tc, "error96", test_get_messagetype(msg));
CuAssertIntEquals(tc, 1, env.dst->number); CuAssertIntEquals(tc, 1, env.dst->number);
CuAssertIntEquals(tc, 1, env.src->number); CuAssertIntEquals(tc, 1, env.src->number);
test_cleanup(); test_cleanup();
@ -137,7 +137,7 @@ static void test_give_men_requires_contact(CuTest * tc) {
env.f2 = test_create_faction(0); env.f2 = test_create_faction(0);
setup_give(&env); setup_give(&env);
msg = give_men(1, env.src, env.dst, NULL); msg = give_men(1, env.src, env.dst, NULL);
CuAssertStrEquals(tc, "feedback_no_contact", (const char *)msg->parameters[3].v); CuAssertStrEquals(tc, "feedback_no_contact", test_get_messagetype(msg));
CuAssertIntEquals(tc, 1, env.dst->number); CuAssertIntEquals(tc, 1, env.dst->number);
CuAssertIntEquals(tc, 1, env.src->number); CuAssertIntEquals(tc, 1, env.src->number);
test_cleanup(); test_cleanup();
@ -150,7 +150,7 @@ static void test_give_men_not_to_self(CuTest * tc) {
env.f2 = env.f1 = test_create_faction(0); env.f2 = env.f1 = test_create_faction(0);
setup_give(&env); setup_give(&env);
msg = give_men(1, env.src, env.src, NULL); msg = give_men(1, env.src, env.src, NULL);
CuAssertStrEquals(tc, "error10", (const char *)msg->parameters[3].v); CuAssertStrEquals(tc, "error10", test_get_messagetype(msg));
CuAssertIntEquals(tc, 1, env.src->number); CuAssertIntEquals(tc, 1, env.src->number);
test_cleanup(); test_cleanup();
} }

View file

@ -388,32 +388,6 @@ static void lua_agebuilding(building * b)
} }
} }
static int lua_building_protection(building * b, unit * u)
{
lua_State *L = (lua_State *) global.vm_state;
const char *fname = "building_protection";
int result = 0;
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)b, TOLUA_CAST "building");
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
if (lua_pcall(L, 2, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("building_protection(%s, %s) calling '%s': %s.\n", buildingname(b), unitname(u), fname, error);
lua_pop(L, 1);
} else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
} else {
log_error("building_protection(%s, %s) calling '%s': not a function.\n", buildingname(b), unitname(u), fname);
lua_pop(L, 1);
}
return result;
}
static double lua_building_taxes(building * b, int level) static double lua_building_taxes(building * b, int level)
{ {
lua_State *L = (lua_State *) global.vm_state; lua_State *L = (lua_State *) global.vm_state;
@ -545,8 +519,6 @@ void register_tolua_helpers(void)
at_register(&at_direction); at_register(&at_direction);
at_register(&at_building_action); at_register(&at_building_action);
register_function((pf_generic) & lua_building_protection,
TOLUA_CAST "lua_building_protection");
register_function((pf_generic) & lua_building_taxes, register_function((pf_generic) & lua_building_taxes,
TOLUA_CAST "lua_building_taxes"); TOLUA_CAST "lua_building_taxes");
register_function((pf_generic) & lua_agebuilding, register_function((pf_generic) & lua_agebuilding,

View file

@ -21,6 +21,7 @@ race.test.c
spellbook.test.c spellbook.test.c
curse.test.c curse.test.c
jsonconf.test.c jsonconf.test.c
messages.test.c
) )
SET(_FILES SET(_FILES

View file

@ -45,6 +45,9 @@ extern "C" {
int maxsize; /* maximum size of this type */ int maxsize; /* maximum size of this type */
int reqsize; /* size of object using up 1 set of requirement. */ int reqsize; /* size of object using up 1 set of requirement. */
int defense_bonus; /* protection bonus (defense) during combat */
int close_combat_bonus; /* close combat attack bonus*/
int ranged_bonus; /* ranged attack bonus */
requirement *materials; /* material req'd to build one object */ requirement *materials; /* material req'd to build one object */
const struct building_type *btype; const struct building_type *btype;
/* building type required to make this thing */ /* building type required to make this thing */

View file

@ -305,7 +305,7 @@ const building_type *findbuildingtype(const char *name,
for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) { for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
building_type *btype = (building_type *)ql_get(ql, qi); building_type *btype = (building_type *)ql_get(ql, qi);
const char *n = locale_string(lang, btype->_name); const char *n = LOC(lang, btype->_name);
type.v = (void *)btype; type.v = (void *)btype;
addtoken(&bn->names, n, type); addtoken(&bn->names, n, type);
} }
@ -316,12 +316,32 @@ const building_type *findbuildingtype(const char *name,
return (const building_type *)type.v; return (const building_type *)type.v;
} }
static int eressea_building_protection(building * b, unit * u) static int building_protection(building * b, unit * u, building_bonus bonus)
{ {
int beff = buildingeffsize(b, false) - 1;
/* -1 because the tradepost has no protection value */
return beff; int i = 0;
int bsize = buildingeffsize(b, false);
const construction *cons = b->type->construction;
if (!cons) {
return 0;
}
for (i = 0; i < bsize; i++)
{
cons = cons->improvement;
}
switch (bonus)
{
case DEFENSE_BONUS:
return cons->defense_bonus;
case CLOSE_COMBAT_ATTACK_BONUS:
return cons->close_combat_bonus;
case RANGED_ATTACK_BONUS:
return cons->ranged_bonus;
default:
return 0;
}
} }
static int meropis_building_protection(building * b, unit * u) static int meropis_building_protection(building * b, unit * u)
@ -331,8 +351,8 @@ static int meropis_building_protection(building * b, unit * u)
void register_buildings(void) void register_buildings(void)
{ {
register_function((pf_generic)& eressea_building_protection, register_function((pf_generic)& building_protection,
"eressea_building_protection"); "building_protection");
register_function((pf_generic)& meropis_building_protection, register_function((pf_generic)& meropis_building_protection,
"meropis_building_protection"); "meropis_building_protection");
register_function((pf_generic)& init_smithy, "init_smithy"); register_function((pf_generic)& init_smithy, "init_smithy");

View file

@ -48,6 +48,12 @@ extern "C" {
#define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */ #define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */
#define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */
typedef enum {
DEFENSE_BONUS,
CLOSE_COMBAT_ATTACK_BONUS,
RANGED_ATTACK_BONUS,
} building_bonus;
typedef struct building_type { typedef struct building_type {
char *_name; char *_name;
@ -66,7 +72,7 @@ extern "C" {
const struct building * b, int size); const struct building * b, int size);
void (*init) (struct building_type *); void (*init) (struct building_type *);
void (*age) (struct building *); void (*age) (struct building *);
int (*protection) (struct building *, struct unit *); int (*protection) (struct building *, struct unit *, building_bonus);
double (*taxes) (const struct building *, int size); double (*taxes) (const struct building *, int size);
struct attrib *attribs; struct attrib *attribs;
} building_type; } building_type;

View file

@ -144,7 +144,7 @@ bool ExpensiveMigrants(void)
gamecookie = global.cookie; gamecookie = global.cookie;
value = get_param_int(global.parameters, "study.expensivemigrants", 0); value = get_param_int(global.parameters, "study.expensivemigrants", 0);
} }
return value; return value!=0;
} }
/** Specifies automatic alliance modes. /** Specifies automatic alliance modes.
@ -932,12 +932,12 @@ void init_terrains_translation(const struct locale *lang) {
variant var; variant var;
const char *name; const char *name;
var.v = (void *)terrain; var.v = (void *)terrain;
name = LOC(lang, terrain->_name); name = locale_string(lang, terrain->_name, false);
if (name) { if (name) {
addtoken(tokens, name, var); addtoken(tokens, name, var);
} }
else { else {
log_error("no translation for terrain %s in locale %s", terrain->_name, locale_name(lang)); log_debug("no translation for terrain %s in locale %s", terrain->_name, locale_name(lang));
} }
} }
} }
@ -951,12 +951,12 @@ void init_options_translation(const struct locale * lang) {
variant var; variant var;
var.i = i; var.i = i;
if (options[i]) { if (options[i]) {
const char *name = LOC(lang, options[i]); const char *name = locale_string(lang, options[i], false);
if (name) { if (name) {
addtoken(tokens, name, var); addtoken(tokens, name, var);
} }
else { else {
log_error("no translation for OPTION %s in locale %s", options[i], locale_name(lang)); log_debug("no translation for OPTION %s in locale %s", options[i], locale_name(lang));
} }
} }
} }
@ -1006,9 +1006,9 @@ void init_locale(struct locale *lang)
for (rc = races; rc; rc = rc->next) { for (rc = races; rc; rc = rc->next) {
const char *name; const char *name;
var.v = (void *)rc; var.v = (void *)rc;
name = LOC(lang, rc_name_s(rc, NAME_PLURAL)); name = locale_string(lang, rc_name_s(rc, NAME_PLURAL), false);
if (name) addtoken(tokens, name, var); if (name) addtoken(tokens, name, var);
name = LOC(lang, rc_name_s(rc, NAME_SINGULAR)); name = locale_string(lang, rc_name_s(rc, NAME_SINGULAR), false);
if (name) addtoken(tokens, name, var); if (name) addtoken(tokens, name, var);
} }
@ -1693,7 +1693,7 @@ order *default_order(const struct locale *lang)
assert(i < MAXLOCALES); assert(i < MAXLOCALES);
result = defaults[i]; result = defaults[i];
if (!result && usedefault) { if (!result && usedefault) {
const char * str = locale_string(lang, "defaultorder"); const char * str = LOC(lang, "defaultorder");
if (str) { if (str) {
result = defaults[i] = parse_order(str, lang); result = defaults[i] = parse_order(str, lang);
} }

View file

@ -2,7 +2,11 @@
#include "types.h" #include "types.h"
#include "curse.h" #include "curse.h"
#include <kernel/region.h>
#include <kernel/unit.h>
#include <util/attrib.h> #include <util/attrib.h>
#include <util/message.h>
#include <tests.h>
#include <CuTest.h> #include <CuTest.h>
@ -22,9 +26,70 @@ static void test_curse(CuTest * tc)
CuAssertPtrEquals(tc, NULL, result); CuAssertPtrEquals(tc, NULL, result);
} }
typedef struct {
curse *c;
region *r;
unit *u;
} curse_fixture;
static void setup_curse(curse_fixture *fix, const char *name) {
test_cleanup();
fix->r = test_create_region(0, 0, NULL);
fix->u = test_create_unit(test_create_faction(NULL), fix->r);
fix->c = create_curse(fix->u, &fix->r->attribs, ct_find(name), 1.0, 1, 1.0, 0);
}
static void test_magicstreet(CuTest *tc) {
curse_fixture fix;
message *msg;
setup_curse(&fix, "magicstreet");
fix.c->duration = 2;
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::magicstreet", test_get_messagetype(msg));
msg_release(msg);
test_cleanup();
}
static void test_magicstreet_warning(CuTest *tc) {
curse_fixture fix;
message *msg;
setup_curse(&fix, "magicstreet");
fix.c->duration = 1;
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::magicstreetwarn", test_get_messagetype(msg));
msg_release(msg);
test_cleanup();
}
static void test_good_dreams(CuTest *tc) {
curse_fixture fix;
message *msg;
setup_curse(&fix, "gbdream");
fix.c->effect = 1;
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::gooddream", test_get_messagetype(msg));
msg_release(msg);
test_cleanup();
}
static void test_bad_dreams(CuTest *tc) {
curse_fixture fix;
message *msg;
setup_curse(&fix, "gbdream");
fix.c->effect = -1;
msg = fix.c->type->curseinfo(fix.r, TYP_REGION, fix.c, 0);
CuAssertStrEquals(tc, "curseinfo::baddream", test_get_messagetype(msg));
msg_release(msg);
test_cleanup();
}
CuSuite *get_curse_suite(void) CuSuite *get_curse_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_curse); SUITE_ADD_TEST(suite, test_curse);
SUITE_ADD_TEST(suite, test_magicstreet);
SUITE_ADD_TEST(suite, test_magicstreet_warning);
SUITE_ADD_TEST(suite, test_good_dreams);
SUITE_ADD_TEST(suite, test_bad_dreams);
return suite; return suite;
} }

View file

@ -280,9 +280,7 @@ unit *addplayer(region * r, faction * f)
bool checkpasswd(const faction * f, const char *passwd) bool checkpasswd(const faction * f, const char *passwd)
{ {
if (passwd && unicode_utf8_strcasecmp(f->passw, passwd) == 0) return (passwd && unicode_utf8_strcasecmp(f->passw, passwd) == 0);
return true;
return false;
} }
variant read_faction_reference(struct storage * store) variant read_faction_reference(struct storage * store)

View file

@ -82,7 +82,6 @@ typedef struct faction {
int no_units; int no_units;
struct ally *allies; struct ally *allies;
struct group *groups; struct group *groups;
bool alive; /* enno: sollte ein flag werden */
int nregions; int nregions;
int money; int money;
#if SCORE_MODULE #if SCORE_MODULE
@ -104,6 +103,7 @@ typedef struct faction {
struct item *items; /* items this faction can claim */ struct item *items; /* items this faction can claim */
struct seen_region **seen; struct seen_region **seen;
struct quicklist *seen_factions; struct quicklist *seen_factions;
bool alive; /* enno: sollte ein flag werden */
} faction; } faction;
extern struct faction *factions; extern struct faction *factions;

View file

@ -1045,7 +1045,7 @@ static int add_resourcename_cb(const void * match, const void * key, size_t keyl
cb_get_kv(match, &rtype, sizeof(rtype)); cb_get_kv(match, &rtype, sizeof(rtype));
for (i = 0; i != 2; ++i) { for (i = 0; i != 2; ++i) {
char buffer[128]; char buffer[128];
const char * name = locale_string(lang, resourcename(rtype, (i==0) ? 0 : NMF_PLURAL)); const char * name = LOC(lang, resourcename(rtype, (i == 0) ? 0 : NMF_PLURAL));
if (name && transliterate(buffer, sizeof(buffer), name)) { if (name && transliterate(buffer, sizeof(buffer), name)) {
size_t len = strlen(buffer); size_t len = strlen(buffer);
@ -1096,7 +1096,7 @@ static int add_itemname_cb(const void * match, const void * key, size_t keylen,
int i; int i;
for (i = 0; i != 2; ++i) { for (i = 0; i != 2; ++i) {
char buffer[128]; char buffer[128];
const char * name = locale_string(lang, resourcename(rtype, (i == 0) ? 0 : NMF_PLURAL)); const char * name = LOC(lang, resourcename(rtype, (i == 0) ? 0 : NMF_PLURAL));
if (name && transliterate(buffer, sizeof(buffer), name)) { if (name && transliterate(buffer, sizeof(buffer), name)) {
size_t len = strlen(buffer); size_t len = strlen(buffer);

View file

@ -193,11 +193,11 @@ extern "C" {
typedef struct armor_type { typedef struct armor_type {
const item_type *itype; const item_type *itype;
unsigned int flags;
double penalty; double penalty;
double magres; double magres;
int prot; int prot;
float projectile; /* chance, dass ein projektil abprallt */ float projectile; /* chance, dass ein projektil abprallt */
unsigned int flags;
} armor_type; } armor_type;
#define WTF_NONE 0x00 #define WTF_NONE 0x00
@ -223,7 +223,7 @@ extern "C" {
int reload; /* time to reload this weapon */ int reload; /* time to reload this weapon */
weapon_mod *modifiers; weapon_mod *modifiers;
/* --- functions --- */ /* --- functions --- */
bool(*attack) (const struct troop *, const struct weapon_type *, bool(*attack) (const struct troop *, const struct weapon_type *,
int *deaths); int *deaths);
} weapon_type; } weapon_type;

View file

@ -143,6 +143,27 @@ static void test_fix_demand(CuTest *tc) {
test_cleanup(); test_cleanup();
} }
static void test_core_resources(CuTest *tc) {
resource_type * rtype;
test_cleanup();
init_resources();
CuAssertPtrNotNull(tc, rtype = rt_find("money"));
CuAssertPtrNotNull(tc, rtype->itype);
CuAssertPtrNotNull(tc, rtype->uchange);
CuAssertPtrNotNull(tc, rtype->itype->give);
CuAssertPtrNotNull(tc, rtype = rt_find("peasant"));
CuAssertPtrEquals(tc, 0, rtype->itype);
CuAssertPtrNotNull(tc, rtype = rt_find("person"));
CuAssertPtrEquals(tc, 0, rtype->itype);
CuAssertPtrNotNull(tc, rtype = rt_find("permaura"));
CuAssertPtrEquals(tc, 0, rtype->itype);
CuAssertPtrNotNull(tc, rtype = rt_find("hp"));
CuAssertPtrEquals(tc, 0, rtype->itype);
CuAssertPtrNotNull(tc, rtype = rt_find("aura"));
CuAssertPtrEquals(tc, 0, rtype->itype);
test_cleanup();
}
CuSuite *get_item_suite(void) CuSuite *get_item_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
@ -153,5 +174,6 @@ CuSuite *get_item_suite(void)
SUITE_ADD_TEST(suite, test_finditemtype); SUITE_ADD_TEST(suite, test_finditemtype);
SUITE_ADD_TEST(suite, test_findresourcetype); SUITE_ADD_TEST(suite, test_findresourcetype);
SUITE_ADD_TEST(suite, test_fix_demand); SUITE_ADD_TEST(suite, test_fix_demand);
SUITE_ADD_TEST(suite, test_core_resources);
return suite; return suite;
} }

View file

@ -373,8 +373,8 @@ static void test_skills(CuTest * tc)
CuAssertIntEquals(tc, SK_CROSSBOW, get_skill("kreuz", lang)); CuAssertIntEquals(tc, SK_CROSSBOW, get_skill("kreuz", lang));
CuAssertIntEquals(tc, SK_ALCHEMY, get_skill("alchemie", lang)); CuAssertIntEquals(tc, SK_ALCHEMY, get_skill("alchemie", lang));
CuAssertStrEquals(tc, "ALCHEMIE", locale_string(lang, "skill::alchemy")); CuAssertStrEquals(tc, "ALCHEMIE", LOC(lang, "skill::alchemy"));
CuAssertStrEquals(tc, "ARMBRUST", locale_string(lang, "skill::crossbow")); CuAssertStrEquals(tc, "ARMBRUST", LOC(lang, "skill::crossbow"));
test_cleanup(); test_cleanup();
} }
@ -396,8 +396,8 @@ static void test_keywords(CuTest * tc)
CuAssertIntEquals(tc, K_STUDY, get_keyword("lerne", lang)); CuAssertIntEquals(tc, K_STUDY, get_keyword("lerne", lang));
CuAssertIntEquals(tc, K_MOVE, get_keyword("nach", lang)); CuAssertIntEquals(tc, K_MOVE, get_keyword("nach", lang));
CuAssertStrEquals(tc, "LERNEN", locale_string(lang, "keyword::study")); CuAssertStrEquals(tc, "LERNEN", LOC(lang, "keyword::study"));
CuAssertStrEquals(tc, "NACH", locale_string(lang, "keyword::move")); CuAssertStrEquals(tc, "NACH", LOC(lang, "keyword::move"));
test_cleanup(); test_cleanup();
} }
@ -413,10 +413,10 @@ static void test_strings(CuTest * tc)
test_cleanup(); test_cleanup();
lang = get_or_create_locale("de"); lang = get_or_create_locale("de");
CuAssertPtrNotNull(tc, lang); CuAssertPtrNotNull(tc, lang);
CuAssertPtrEquals(tc, NULL, (void *)locale_string(lang, "move")); CuAssertPtrEquals(tc, NULL, (void *)LOC(lang, "move"));
json_config(json); json_config(json);
CuAssertStrEquals(tc, "NACH", locale_string(lang, "move")); CuAssertStrEquals(tc, "NACH", LOC(lang, "move"));
CuAssertStrEquals(tc, "LERNEN", locale_string(lang, "study")); CuAssertStrEquals(tc, "LERNEN", LOC(lang, "study"));
} }
static void test_infinitive_from_config(CuTest *tc) { static void test_infinitive_from_config(CuTest *tc) {

View file

@ -17,7 +17,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #include <platform.h>
#include <kernel/config.h>
#include "messages.h" #include "messages.h"
/* kernel includes */ /* kernel includes */
@ -140,7 +139,7 @@ struct message *msg_feedback(const struct unit *u, struct order *ord,
message *msg_message(const char *name, const char *sig, ...) message *msg_message(const char *name, const char *sig, ...)
/* msg_message("oops_error", "unit region command", u, r, cmd) */ /* msg_message("oops_error", "unit region command", u, r, cmd) */
{ {
va_list marker; va_list vargs;
const message_type *mtype = mt_find(name); const message_type *mtype = mt_find(name);
char paramname[64]; char paramname[64];
const char *ic = sig; const char *ic = sig;
@ -155,7 +154,7 @@ message *msg_message(const char *name, const char *sig, ...)
return NULL; return NULL;
} }
va_start(marker, sig); va_start(vargs, sig);
while (*ic && !isalnum(*ic)) while (*ic && !isalnum(*ic))
ic++; ic++;
while (*ic) { while (*ic) {
@ -172,9 +171,9 @@ message *msg_message(const char *name, const char *sig, ...)
} }
if (i != mtype->nparameters) { if (i != mtype->nparameters) {
if (mtype->types[i]->vtype == VAR_VOIDPTR) { if (mtype->types[i]->vtype == VAR_VOIDPTR) {
args[i].v = va_arg(marker, void *); args[i].v = va_arg(vargs, void *);
} else if (mtype->types[i]->vtype == VAR_INT) { } else if (mtype->types[i]->vtype == VAR_INT) {
args[i].i = va_arg(marker, int); args[i].i = va_arg(vargs, int);
} else { } else {
assert(!"unknown variant type"); assert(!"unknown variant type");
} }
@ -185,7 +184,7 @@ message *msg_message(const char *name, const char *sig, ...)
while (*ic && !isalnum(*ic)) while (*ic && !isalnum(*ic))
ic++; ic++;
} }
va_end(marker); va_end(vargs);
return msg_create(mtype, args); return msg_create(mtype, args);
} }

View file

@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #endif
#include <kernel/types.h>
#include <util/message.h> #include <util/message.h>
struct faction; struct faction;

View file

@ -0,0 +1,44 @@
#include <platform.h>
#include "messages.h"
#include <CuTest.h>
#include <tests.h>
void test_missing_message(CuTest *tc) {
message *msg;
msg = msg_message("unknown", "unit", NULL);
CuAssertPtrNotNull(tc, msg);
CuAssertPtrNotNull(tc, msg->type);
CuAssertStrEquals(tc, msg->type->name, "missing_message");
msg_release(msg);
}
void test_message(CuTest *tc) {
message *msg;
// const char * args[] = { }
message_type *mtype = mt_new("custom", NULL);
mt_register(mtype);
CuAssertPtrEquals(tc, mtype, (void *)mt_find("custom"));
CuAssertIntEquals(tc, 0, mtype->nparameters);
CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
CuAssertPtrEquals(tc, NULL, (void *)mtype->types);
msg = msg_message("custom", "");
CuAssertPtrNotNull(tc, msg);
CuAssertIntEquals(tc, 1, msg->refcount);
CuAssertPtrEquals(tc, NULL, msg->parameters);
CuAssertPtrEquals(tc, mtype, (void *)msg->type);
CuAssertPtrEquals(tc, msg, msg_addref(msg));
CuAssertIntEquals(tc, 2, msg->refcount);
msg_release(msg);
CuAssertIntEquals(tc, 1, msg->refcount);
msg_release(msg);
test_cleanup();
}
CuSuite *get_messages_suite(void) {
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_missing_message);
SUITE_ADD_TEST(suite, test_message);
return suite;
}

View file

@ -388,8 +388,6 @@ order *parse_order(const char *s, const struct locale * lang)
bool is_repeated(const order * ord) bool is_repeated(const order * ord)
{ {
keyword_t kwd = ORD_KEYWORD(ord); keyword_t kwd = ORD_KEYWORD(ord);
int result = 0;
switch (kwd) { switch (kwd) {
case K_CAST: case K_CAST:
case K_BUY: case K_BUY:
@ -411,13 +409,12 @@ bool is_repeated(const order * ord)
case K_MAKE: case K_MAKE:
case K_LOOT: case K_LOOT:
case K_DESTROY: case K_DESTROY:
result = 1; return true;
break;
default: default:
result = 0; break;
} }
return result; return false;
} }
/** /**
@ -431,7 +428,6 @@ bool is_repeated(const order * ord)
bool is_exclusive(const order * ord) bool is_exclusive(const order * ord)
{ {
keyword_t kwd = ORD_KEYWORD(ord); keyword_t kwd = ORD_KEYWORD(ord);
int result = 0;
switch (kwd) { switch (kwd) {
case K_MOVE: case K_MOVE:
@ -452,13 +448,12 @@ bool is_exclusive(const order * ord)
case K_MAKE: case K_MAKE:
case K_LOOT: case K_LOOT:
case K_DESTROY: case K_DESTROY:
result = 1; return true;
break;
default: default:
result = 0; break;
} }
return result; return false;
} }
/** /**

View file

@ -177,7 +177,11 @@ race *rc_get_or_create(const char *zName)
rc = (race *)calloc(sizeof(race), 1); rc = (race *)calloc(sizeof(race), 1);
rc->hitpoints = 1; rc->hitpoints = 1;
rc->weight = PERSON_WEIGHT;
rc->capacity = 540;
rc->recruit_multi = 1.0F; rc->recruit_multi = 1.0F;
rc->regaura = 1.0F;
rc->speed = 1.0F;
if (strchr(zName, ' ') != NULL) { if (strchr(zName, ' ') != NULL) {
log_error("race '%s' has an invalid name. remove spaces\n", zName); log_error("race '%s' has an invalid name. remove spaces\n", zName);
assert(strchr(zName, ' ') == NULL); assert(strchr(zName, ' ') == NULL);

View file

@ -140,14 +140,13 @@ extern "C" {
int at_bonus; /* Verändert den Angriffsskill (default: 0) */ int at_bonus; /* Verändert den Angriffsskill (default: 0) */
int df_bonus; /* Verändert den Verteidigungskill (default: 0) */ int df_bonus; /* Verändert den Verteidigungskill (default: 0) */
const struct spell *precombatspell; const struct spell *precombatspell;
struct att attack[10];
signed char bonus[MAXSKILLS];
signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */ signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */
bool __remove_me_nonplayer;
int flags; int flags;
int battle_flags; int battle_flags;
int ec_flags; int ec_flags;
race_t oldfamiliars[MAXMAGIETYP]; race_t oldfamiliars[MAXMAGIETYP];
struct att attack[10];
signed char bonus[MAXSKILLS];
const char *(*generate_name) (const struct unit *); const char *(*generate_name) (const struct unit *);
const char *(*describe) (const struct unit *, const struct locale *); const char *(*describe) (const struct unit *, const struct locale *);

View file

@ -8,17 +8,43 @@
#include <assert.h> #include <assert.h>
static void test_rc_name(CuTest *tc) { static void test_rc_name(CuTest *tc) {
struct race *rc = test_create_race("human"); struct race *rc;
test_cleanup();
rc = test_create_race("human");
CuAssertStrEquals(tc, "race::human", rc_name_s(rc, NAME_SINGULAR)); CuAssertStrEquals(tc, "race::human", rc_name_s(rc, NAME_SINGULAR));
CuAssertStrEquals(tc, "race::human_p", rc_name_s(rc, NAME_PLURAL)); CuAssertStrEquals(tc, "race::human_p", rc_name_s(rc, NAME_PLURAL));
CuAssertStrEquals(tc, "race::human_d", rc_name_s(rc, NAME_DEFINITIVE)); CuAssertStrEquals(tc, "race::human_d", rc_name_s(rc, NAME_DEFINITIVE));
CuAssertStrEquals(tc, "race::human_x", rc_name_s(rc, NAME_CATEGORY)); CuAssertStrEquals(tc, "race::human_x", rc_name_s(rc, NAME_CATEGORY));
test_cleanup();
}
static void test_rc_defaults(CuTest *tc) {
struct race *rc;
test_cleanup();
rc = rc_get_or_create("human");
CuAssertStrEquals(tc, "human", rc->_name);
CuAssertDblEquals(tc, 0.0, rc->magres, 0.0);
CuAssertDblEquals(tc, 0.0, rc->maxaura, 0.0);
CuAssertDblEquals(tc, 1.0, rc->recruit_multi, 0.0);
CuAssertDblEquals(tc, 1.0, rc->regaura, 0.0);
CuAssertDblEquals(tc, 1.0, rc->speed, 0.0);
CuAssertIntEquals(tc, 0, rc->flags);
CuAssertIntEquals(tc, 0, rc->recruitcost);
CuAssertIntEquals(tc, 0, rc->maintenance);
CuAssertIntEquals(tc, 540, rc->capacity);
CuAssertIntEquals(tc, 1, rc->hitpoints);
CuAssertIntEquals(tc, 0, rc->armor);
CuAssertIntEquals(tc, 0, rc->at_bonus);
CuAssertIntEquals(tc, 0, rc->df_bonus);
CuAssertIntEquals(tc, PERSON_WEIGHT, rc->weight);
test_cleanup();
} }
CuSuite *get_race_suite(void) CuSuite *get_race_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_rc_name); SUITE_ADD_TEST(suite, test_rc_name);
SUITE_ADD_TEST(suite, test_rc_defaults);
return suite; return suite;
} }

View file

@ -1568,7 +1568,7 @@ int readgame(const char *filename, int backup)
sh->type = st_find(name); sh->type = st_find(name);
if (sh->type == NULL) { if (sh->type == NULL) {
/* old datafiles */ /* old datafiles */
sh->type = st_find((const char *)locale_string(default_locale, name)); sh->type = st_find((const char *)LOC(default_locale, name));
} }
assert(sh->type || !"ship_type not registered!"); assert(sh->type || !"ship_type not registered!");

View file

@ -76,7 +76,7 @@ const ship_type *findshiptype(const char *name, const struct locale *lang)
for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) {
ship_type *stype = (ship_type *)ql_get(ql, qi); ship_type *stype = (ship_type *)ql_get(ql, qi);
variant var2; variant var2;
const char *n = locale_string(lang, stype->_name); const char *n = LOC(lang, stype->_name);
var2.v = (void *)stype; var2.v = (void *)stype;
addtoken(&sn->names, n, var2); addtoken(&sn->names, n, var2);
} }

View file

@ -1725,21 +1725,23 @@ int unit_max_hp(const unit * u)
get_param_int(global.parameters, "rules.stamina", STAMINA_AFFECTS_HP); get_param_int(global.parameters, "rules.stamina", STAMINA_AFFECTS_HP);
} }
h = u_race(u)->hitpoints; h = u_race(u)->hitpoints;
if (heal_ct == NULL)
heal_ct = ct_find("healingzone");
if (rules_stamina & 1) { if (rules_stamina & 1) {
p = pow(effskill(u, SK_STAMINA) / 2.0, 1.5) * 0.2; p = pow(effskill(u, SK_STAMINA) / 2.0, 1.5) * 0.2;
h += (int)(h * p + 0.5); h += (int)(h * p + 0.5);
} }
/* der healing curse veraendert die maximalen hp */ /* der healing curse veraendert die maximalen hp */
if (heal_ct) { if (u->region) {
curse *c = get_curse(u->region->attribs, heal_ct); if (heal_ct == NULL)
if (c) { heal_ct = ct_find("healingzone");
h = (int)(h * (1.0 + (curse_geteffect(c) / 100))); if (heal_ct) {
curse *c = get_curse(u->region->attribs, heal_ct);
if (c) {
h = (int)(h * (1.0 + (curse_geteffect(c) / 100)));
}
} }
} }
return h; return h;
} }
@ -1883,7 +1885,7 @@ char *write_unitname(const unit * u, char *buffer, size_t size)
} else { } else {
const struct locale * lang = u->faction ? u->faction->locale : default_locale; const struct locale * lang = u->faction ? u->faction->locale : default_locale;
const char * name = rc_name_s(u->_race, u->number == 1 ? NAME_SINGULAR : NAME_PLURAL); const char * name = rc_name_s(u->_race, u->number == 1 ? NAME_SINGULAR : NAME_PLURAL);
slprintf(buffer, size, "%s (%s)", locale_string(lang, name), itoa36(u->no)); slprintf(buffer, size, "%s (%s)", LOC(lang, name), itoa36(u->no));
} }
buffer[size - 1] = 0; buffer[size - 1] = 0;
return buffer; return buffer;
@ -1902,8 +1904,8 @@ bool unit_name_equals_race(const unit *u) {
rc_name(u->_race, NAME_SINGULAR, sing, sizeof(sing)); rc_name(u->_race, NAME_SINGULAR, sing, sizeof(sing));
rc_name(u->_race, NAME_PLURAL, plur, sizeof(plur)); rc_name(u->_race, NAME_PLURAL, plur, sizeof(plur));
if (strcmp(u->name, sing) == 0 || strcmp(u->name, plur) == 0 || if (strcmp(u->name, sing) == 0 || strcmp(u->name, plur) == 0 ||
strcmp(u->name, locale_string(lang, sing)) == 0 || strcmp(u->name, LOC(lang, sing)) == 0 ||
strcmp(u->name, locale_string(lang, plur)) == 0) { strcmp(u->name, LOC(lang, plur)) == 0) {
return true; return true;
} }
} }

View file

@ -167,7 +167,10 @@ construction ** consPtr)
con->maxsize = xml_ivalue(node, "maxsize", -1); con->maxsize = xml_ivalue(node, "maxsize", -1);
con->minskill = xml_ivalue(node, "minskill", -1); con->minskill = xml_ivalue(node, "minskill", -1);
con->reqsize = xml_ivalue(node, "reqsize", -1); con->reqsize = xml_ivalue(node, "reqsize", -1);
con->defense_bonus = xml_ivalue(node, "defense_bonus", 0);
con->close_combat_bonus = xml_ivalue(node, "close_combat_bonus", 0);
con->ranged_bonus = xml_ivalue(node, "ranged_bonus", 0);
propValue = xmlGetProp(node, BAD_CAST "building"); propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) { if (propValue != NULL) {
con->btype = bt_get_or_create((const char *)propValue); con->btype = bt_get_or_create((const char *)propValue);
@ -297,7 +300,7 @@ static int parse_buildings(xmlDocPtr doc)
btype->age = (void(*)(struct building *))fun; btype->age = (void(*)(struct building *))fun;
} }
else if (strcmp((const char *)propValue, "protection") == 0) { else if (strcmp((const char *)propValue, "protection") == 0) {
btype->protection = (int(*)(struct building *, struct unit *))fun; btype->protection = (int(*)(struct building *, struct unit *, building_bonus))fun;
} }
else if (strcmp((const char *)propValue, "taxes") == 0) { else if (strcmp((const char *)propValue, "taxes") == 0) {
btype->taxes = (double(*)(const struct building *, int))fun; btype->taxes = (double(*)(const struct building *, int))fun;
@ -1623,22 +1626,22 @@ static int parse_races(xmlDocPtr doc)
rc->def_damage = _strdup((const char *)propValue); rc->def_damage = _strdup((const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
rc->magres = (float)xml_fvalue(node, "magres", 0.0); rc->magres = (float)xml_fvalue(node, "magres", rc->magres);
rc->maxaura = (float)xml_fvalue(node, "maxaura", 0.0); rc->maxaura = (float)xml_fvalue(node, "maxaura", rc->maxaura);
rc->regaura = (float)xml_fvalue(node, "regaura", 1.0); rc->regaura = (float)xml_fvalue(node, "regaura", rc->regaura);
rc->recruitcost = xml_ivalue(node, "recruitcost", 0); rc->recruitcost = xml_ivalue(node, "recruitcost", rc->recruitcost);
rc->maintenance = xml_ivalue(node, "maintenance", 0); rc->maintenance = xml_ivalue(node, "maintenance", rc->maintenance);
rc->weight = xml_ivalue(node, "weight", PERSON_WEIGHT); rc->weight = xml_ivalue(node, "weight", rc->weight);
rc->capacity = xml_ivalue(node, "capacity", 540); rc->capacity = xml_ivalue(node, "capacity", rc->capacity);
rc->speed = (float)xml_fvalue(node, "speed", 1.0F); rc->speed = (float)xml_fvalue(node, "speed", rc->speed);
rc->hitpoints = xml_ivalue(node, "hp", 0); rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints);
rc->armor = (char)xml_ivalue(node, "ac", 0); rc->armor = (char)xml_ivalue(node, "ac", rc->armor);
study_speed_base = xml_ivalue(node, "studyspeed", 0); study_speed_base = xml_ivalue(node, "studyspeed", 0);
rc->at_default = (char)xml_ivalue(node, "unarmedattack", -2); rc->at_default = (char)xml_ivalue(node, "unarmedattack", -2);
rc->df_default = (char)xml_ivalue(node, "unarmeddefense", -2); rc->df_default = (char)xml_ivalue(node, "unarmeddefense", -2);
rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", 0); rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", rc->at_bonus);
rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", 0); rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", rc->df_bonus);
if (!xml_bvalue(node, "playerrace", false)) if (!xml_bvalue(node, "playerrace", false))
rc->flags |= RCF_NPC; rc->flags |= RCF_NPC;

View file

@ -968,7 +968,7 @@ static bool CheckOverload(void)
if (value < 0) { if (value < 0) {
value = get_param_int(global.parameters, "rules.check_overload", 0); value = get_param_int(global.parameters, "rules.check_overload", 0);
} }
return value; return value!=0;
} }
int enter_ship(unit * u, struct order *ord, int id, bool report) int enter_ship(unit * u, struct order *ord, int id, bool report)
@ -1411,11 +1411,11 @@ static void init_prefixnames(void)
for (key = 0; race_prefixes[key]; ++key) { for (key = 0; race_prefixes[key]; ++key) {
variant var; variant var;
const char *pname = const char *pname =
locale_string(lang, mkname("prefix", race_prefixes[key])); LOC(lang, mkname("prefix", race_prefixes[key]));
if (findtoken(in->names, pname, &var) == E_TOK_NOMATCH || var.i != key) { if (findtoken(in->names, pname, &var) == E_TOK_NOMATCH || var.i != key) {
var.i = key; var.i = key;
addtoken(&in->names, pname, var); addtoken(&in->names, pname, var);
addtoken(&in->names, locale_string(lang, mkname("prefix", addtoken(&in->names, LOC(lang, mkname("prefix",
race_prefixes[key])), var); race_prefixes[key])), var);
} }
} }
@ -2209,7 +2209,7 @@ static bool display_item(faction * f, unit * u, const item_type * itype)
info = locale_getstring(f->locale, key); info = locale_getstring(f->locale, key);
if (info == NULL) { if (info == NULL) {
info = locale_string(f->locale, mkname("iteminfo", "no_info")); info = LOC(f->locale, mkname("iteminfo", "no_info"));
} }
ADDMSG(&f->msgs, msg_message("displayitem", "weight item description", ADDMSG(&f->msgs, msg_message("displayitem", "weight item description",
itype->weight, itype->rtype, info)); itype->weight, itype->rtype, info));
@ -2261,7 +2261,7 @@ static bool display_race(faction * f, unit * u, const race * rc)
key = mkname("raceinfo", rc->_name); key = mkname("raceinfo", rc->_name);
info = locale_getstring(f->locale, key); info = locale_getstring(f->locale, key);
if (info == NULL) { if (info == NULL) {
info = locale_string(f->locale, mkname("raceinfo", "no_info")); info = LOC(f->locale, mkname("raceinfo", "no_info"));
} }
bytes = (int)strlcpy(bufp, info, size); bytes = (int)strlcpy(bufp, info, size);
@ -4269,6 +4269,36 @@ static void enter_2(region * r)
do_enter(r, 1); do_enter(r, 1);
} }
static bool help_enter(unit *uo, unit *u) {
return uo->faction == u->faction || alliedunit(uo, u->faction, HELP_GUARD);
}
void force_leave(region *r) {
unit *u;
for (u = r->units; u; u = u->next) {
unit *uo = NULL;
if (u->building) {
uo = building_owner(u->building);
}
if (u->ship && r->land) {
uo = ship_owner(u->ship);
}
if (uo && !help_enter(uo, u)) {
message *msg = NULL;
if (u->building) {
msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building);
}
else {
msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship);
}
if (msg) {
ADDMSG(&u->faction->msgs, msg);
}
leave(u, false);
}
}
}
static void maintain_buildings_1(region * r) static void maintain_buildings_1(region * r)
{ {
maintain_buildings(r, false); maintain_buildings(r, false);
@ -4306,15 +4336,15 @@ void init_processor(void)
int p; int p;
p = 10; p = 10;
add_proc_global(p, &new_units, "Neue Einheiten erschaffen"); add_proc_global(p, new_units, "Neue Einheiten erschaffen");
p += 10; p += 10;
add_proc_unit(p, update_long_order, "Langen Befehl aktualisieren"); add_proc_unit(p, update_long_order, "Langen Befehl aktualisieren");
add_proc_order(p, K_BANNER, banner_cmd, 0, NULL); add_proc_order(p, K_BANNER, banner_cmd, 0, NULL);
add_proc_order(p, K_EMAIL, &email_cmd, 0, NULL); add_proc_order(p, K_EMAIL, email_cmd, 0, NULL);
add_proc_order(p, K_PASSWORD, &password_cmd, 0, NULL); add_proc_order(p, K_PASSWORD, password_cmd, 0, NULL);
add_proc_order(p, K_SEND, &send_cmd, 0, NULL); add_proc_order(p, K_SEND, send_cmd, 0, NULL);
add_proc_order(p, K_GROUP, &group_cmd, 0, NULL); add_proc_order(p, K_GROUP, group_cmd, 0, NULL);
p += 10; p += 10;
add_proc_order(p, K_QUIT, &quit_cmd, 0, NULL); add_proc_order(p, K_QUIT, &quit_cmd, 0, NULL);
@ -4331,46 +4361,47 @@ void init_processor(void)
if (get_param_int(global.parameters, "rules.alliances", 0) == 1) { if (get_param_int(global.parameters, "rules.alliances", 0) == 1) {
p += 10; p += 10;
add_proc_global(p, &alliance_cmd, NULL); add_proc_global(p, alliance_cmd, NULL);
} }
p += 10; p += 10;
add_proc_region(p, do_contact, "Kontaktieren"); add_proc_region(p, do_contact, "Kontaktieren");
add_proc_order(p, K_MAIL, &mail_cmd, 0, "Botschaften"); add_proc_order(p, K_MAIL, mail_cmd, 0, "Botschaften");
p += 10; /* all claims must be done before we can USE */ p += 10; /* all claims must be done before we can USE */
add_proc_region(p, &enter_1, "Betreten (1. Versuch)"); /* for GIVE CONTROL */ add_proc_region(p, &enter_1, "Betreten (1. Versuch)"); /* for GIVE CONTROL */
add_proc_order(p, K_USE, &use_cmd, 0, "Benutzen"); add_proc_order(p, K_USE, use_cmd, 0, "Benutzen");
p += 10; /* in case it has any effects on alliance victories */ p += 10; /* in case it has any effects on alliance victories */
add_proc_order(p, K_GIVE, &give_control_cmd, 0, "GIB KOMMANDO"); add_proc_order(p, K_GIVE, give_control_cmd, 0, "GIB KOMMANDO");
p += 10; /* in case it has any effects on alliance victories */ p += 10; /* in case it has any effects on alliance victories */
add_proc_order(p, K_LEAVE, &leave_cmd, 0, "Verlassen"); add_proc_order(p, K_LEAVE, leave_cmd, 0, "Verlassen");
p += 10; p += 10;
add_proc_region(p, &enter_1, "Betreten (2. Versuch)"); /* to allow a buildingowner to enter the castle pre combat */ add_proc_region(p, enter_1, "Betreten (2. Versuch)"); /* to allow a buildingowner to enter the castle pre combat */
p += 10; p += 10;
add_proc_region(p, &do_battle, "Attackieren"); add_proc_region(p, do_battle, "Attackieren");
if (!keyword_disabled(K_BESIEGE)) { if (!keyword_disabled(K_BESIEGE)) {
p += 10; p += 10;
add_proc_region(p, &do_siege, "Belagern"); add_proc_region(p, do_siege, "Belagern");
} }
p += 10; /* can't allow reserve before siege (weapons) */ p += 10; /* can't allow reserve before siege (weapons) */
add_proc_region(p, &enter_1, "Betreten (3. Versuch)"); /* to claim a castle after a victory and to be able to DESTROY it in the same turn */ add_proc_region(p, enter_1, "Betreten (3. Versuch)"); /* to claim a castle after a victory and to be able to DESTROY it in the same turn */
if (get_param_int(global.parameters, "rules.reserve.twophase", 0)) { if (get_param_int(global.parameters, "rules.reserve.twophase", 0)) {
add_proc_order(p, K_RESERVE, &reserve_self, 0, "RESERVE (self)"); add_proc_order(p, K_RESERVE, &reserve_self, 0, "RESERVE (self)");
p += 10; p += 10;
} }
add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "RESERVE (all)"); add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "RESERVE (all)");
add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL); add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL);
add_proc_unit(p, &follow_unit, "Folge auf Einheiten setzen"); add_proc_unit(p, follow_unit, "Folge auf Einheiten setzen");
p += 10; /* rest rng again before economics */ p += 10; /* rest rng again before economics */
add_proc_region(p, &economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); add_proc_region(p, force_leave, "kick non-allies out of buildings/ships");
add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen");
add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung"); add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung");
p += 10; p += 10;

View file

@ -105,6 +105,7 @@ extern "C" {
bool seefaction(const struct faction *f, const struct region *r, bool seefaction(const struct faction *f, const struct region *r,
const struct unit *u, int modifier); const struct unit *u, int modifier);
int armedmen(const struct unit *u, bool siege_weapons); int armedmen(const struct unit *u, bool siege_weapons);
void force_leave(struct region *r);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -15,6 +15,7 @@
#include <util/base36.h> #include <util/base36.h>
#include <util/language.h> #include <util/language.h>
#include <util/message.h>
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>
@ -226,6 +227,74 @@ static void test_display_cmd(CuTest *tc) {
test_cleanup(); test_cleanup();
} }
static void test_force_leave_buildings(CuTest *tc) {
ally *al;
region *r;
unit *u1, *u2, *u3;
building * b;
message *msg;
test_cleanup();
r = test_create_region(0, 0, test_create_terrain("plain", LAND_REGION));
u1 = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(u1->faction, r);
u3 = test_create_unit(test_create_faction(NULL), r);
b = test_create_building(r, NULL);
u_set_building(u1, b);
building_set_owner(u1);
u_set_building(u2, b);
u_set_building(u3, b);
force_leave(r);
CuAssertPtrEquals_Msg(tc, "owner should not be forecd to leave", b, u1->building);
CuAssertPtrEquals_Msg(tc, "same faction should not be forced to leave", b, u2->building);
CuAssertPtrEquals_Msg(tc, "non-allies should be forced to leave", NULL, u3->building);
msg = test_get_last_message(u3->faction->msgs);
CuAssertStrEquals(tc, "force_leave_building", test_get_messagetype(msg));
u_set_building(u3, b);
al = ally_add(&u1->faction->allies, u3->faction);
al->status = HELP_GUARD;
force_leave(r);
CuAssertPtrEquals_Msg(tc, "allies should not be forced to leave", b, u3->building);
test_cleanup();
}
static void test_force_leave_ships(CuTest *tc) {
region *r;
unit *u1, *u2;
ship *sh;
message *msg;
test_cleanup();
r = test_create_region(0, 0, test_create_terrain("plain", LAND_REGION));
u1 = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
sh = test_create_ship(r, NULL);
u_set_ship(u1, sh);
u_set_ship(u2, sh);
ship_set_owner(u1);
force_leave(r);
CuAssertPtrEquals_Msg(tc, "non-allies should be forced to leave", NULL, u2->ship);
msg = test_get_last_message(u2->faction->msgs);
CuAssertStrEquals(tc, "force_leave_ship", test_get_messagetype(msg));
test_cleanup();
}
static void test_force_leave_ships_on_ocean(CuTest *tc) {
region *r;
unit *u1, *u2;
ship *sh;
test_cleanup();
r = test_create_region(0, 0, test_create_terrain("ocean", SEA_REGION));
u1 = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
sh = test_create_ship(r, NULL);
u_set_ship(u1, sh);
u_set_ship(u2, sh);
ship_set_owner(u1);
force_leave(r);
CuAssertPtrEquals_Msg(tc, "no forcing out of ships on oceans", sh, u2->ship);
test_cleanup();
}
static void test_fishing_feeds_2_people(CuTest * tc) static void test_fishing_feeds_2_people(CuTest * tc)
{ {
const resource_type *rtype; const resource_type *rtype;
@ -649,5 +718,9 @@ CuSuite *get_laws_suite(void)
SUITE_ADD_TEST(suite, test_enter_building); SUITE_ADD_TEST(suite, test_enter_building);
SUITE_ADD_TEST(suite, test_enter_ship); SUITE_ADD_TEST(suite, test_enter_ship);
SUITE_ADD_TEST(suite, test_display_cmd); SUITE_ADD_TEST(suite, test_display_cmd);
SUITE_ADD_TEST(suite, test_force_leave_buildings);
SUITE_ADD_TEST(suite, test_force_leave_ships);
SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean);
return suite; return suite;
} }

View file

@ -104,9 +104,9 @@ bool check_leuchtturm(region * r, faction * f)
{ {
attrib *a; attrib *a;
if (!fval(r->terrain, SEA_REGION)) if (!fval(r->terrain, SEA_REGION)) {
return false; return false;
}
for (a = a_find(r->attribs, &at_lighthouse); a && a->type == &at_lighthouse; for (a = a_find(r->attribs, &at_lighthouse); a && a->type == &at_lighthouse;
a = a->next) { a = a->next) {
building *b = (building *)a->data.v; building *b = (building *)a->data.v;
@ -141,7 +141,7 @@ bool check_leuchtturm(region * r, faction * f)
} }
else { else {
/* E3A rule: no perception req'd */ /* E3A rule: no perception req'd */
return maxd; return true;
} }
} }
} }

View file

@ -304,8 +304,6 @@ int main(int argc, char **argv)
L = lua_init(); L = lua_init();
game_init(); game_init();
register_races();
register_spells();
bind_monsters(L); bind_monsters(L);
err = eressea_run(L, luafile); err = eressea_run(L, luafile);
if (err) { if (err) {

View file

@ -275,7 +275,7 @@ static const char *dragon_name(const unit * u)
if (anzahl > 1) { if (anzahl > 1) {
const char *no_article = strchr((const char *)str, ' '); const char *no_article = strchr((const char *)str, ' ');
assert(no_article); assert(no_article);
/* TODO: GERMAN */ // TODO: localization
sprintf(name, "Die %sn von %s", no_article + 1, rname(u->region, sprintf(name, "Die %sn von %s", no_article + 1, rname(u->region,
default_locale)); default_locale));
} }

View file

@ -26,7 +26,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifdef _MSC_VER #ifdef _MSC_VER
# define VC_EXTRALEAN # define VC_EXTRALEAN
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
#pragma warning(push)
#pragma warning(disable:4820 4255 4668)
# include <windows.h> # include <windows.h>
# include <io.h>
#pragma warning(pop)
# undef MOUSE_MOVED # undef MOUSE_MOVED
# define STDIO_CP 1252 /* log.c, convert to console character set */ # define STDIO_CP 1252 /* log.c, convert to console character set */
# pragma warning (disable: 4201 4214 4514 4115 4711) # pragma warning (disable: 4201 4214 4514 4115 4711)
@ -41,6 +45,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# pragma warning(disable: 4996) # pragma warning(disable: 4996)
/* <name> is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */ /* <name> is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
# pragma warning(disable: 4668) # pragma warning(disable: 4668)
/* <type>: <num> bytes padding after data member <member> */
# pragma warning(disable: 4820)
/* warning C4100: <name> was declared deprecated */ /* warning C4100: <name> was declared deprecated */
#ifndef _CRT_SECURE_NO_DEPRECATE #ifndef _CRT_SECURE_NO_DEPRECATE
@ -113,9 +119,5 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <strings.h> #include <strings.h>
#endif #endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#endif #endif

View file

@ -1025,7 +1025,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f)
if (r->land->ownership) { if (r->land->ownership) {
const char *str = const char *str =
locale_string(f->locale, mkname("morale", itoa10(r->land->morale))); LOC(f->locale, mkname("morale", itoa10(r->land->morale)));
bytes = _snprintf(bufp, size, " %s", str); bytes = _snprintf(bufp, size, " %s", str);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
@ -1100,6 +1100,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f)
if (rule_region_owners()) { if (rule_region_owners()) {
const faction *owner = region_get_owner(r); const faction *owner = region_get_owner(r);
if (owner != NULL) { if (owner != NULL) {
// TODO: localization
bytes = _snprintf(bufp, size, " Die Region ist im Besitz von %s.", bytes = _snprintf(bufp, size, " Die Region ist im Besitz von %s.",
factionname(owner)); factionname(owner));
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
@ -1701,7 +1702,7 @@ show_allies(const faction * f, const ally * allies, char *buf, size_t size)
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
if ((mode & HELP_ALL) == HELP_ALL) { if ((mode & HELP_ALL) == HELP_ALL) {
bytes = (int)strlcpy(bufp, locale_string(f->locale, parameters[P_ANY]), size); bytes = (int)strlcpy(bufp, LOC(f->locale, parameters[P_ANY]), size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} }
@ -1736,7 +1737,7 @@ show_allies(const faction * f, const ally * allies, char *buf, size_t size)
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} }
bytes = (int)strlcpy(bufp, locale_string(f->locale, parameters[p]), size); bytes = (int)strlcpy(bufp, LOC(f->locale, parameters[p]), size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
hh = 1; hh = 1;

View file

@ -150,7 +150,7 @@ const char **name, const char **basename, int *number, bool singular)
if (owner && owner->faction == viewer) { if (owner && owner->faction == viewer) {
if (name) if (name)
*name = *name =
locale_string(viewer->locale, resourcename(i->type->rtype, LOC(viewer->locale, resourcename(i->type->rtype,
((i->number != 1 && !singular) ? GR_PLURAL : 0))); ((i->number != 1 && !singular) ? GR_PLURAL : 0)));
if (basename) if (basename)
*basename = resourcename(i->type->rtype, 0); *basename = resourcename(i->type->rtype, 0);
@ -163,19 +163,19 @@ const char **name, const char **basename, int *number, bool singular)
*number = 1; *number = 1;
if (pp > 50000 && dragonrace(u_race(owner))) { if (pp > 50000 && dragonrace(u_race(owner))) {
if (name) if (name)
*name = locale_string(viewer->locale, "dragonhoard"); *name = LOC(viewer->locale, "dragonhoard");
if (basename) if (basename)
*basename = "dragonhoard"; *basename = "dragonhoard";
} }
else if (pp > 5000) { else if (pp > 5000) {
if (name) if (name)
*name = locale_string(viewer->locale, "moneychest"); *name = LOC(viewer->locale, "moneychest");
if (basename) if (basename)
*basename = "moneychest"; *basename = "moneychest";
} }
else if (pp > 500) { else if (pp > 500) {
if (name) if (name)
*name = locale_string(viewer->locale, "moneybag"); *name = LOC(viewer->locale, "moneybag");
if (basename) if (basename)
*basename = "moneybag"; *basename = "moneybag";
} }
@ -191,7 +191,7 @@ const char **name, const char **basename, int *number, bool singular)
else { else {
if (name) if (name)
*name = *name =
locale_string(viewer->locale, resourcename(i->type->rtype, LOC(viewer->locale, resourcename(i->type->rtype,
NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0))); NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0)));
if (basename) if (basename)
*basename = resourcename(i->type->rtype, NMF_APPEARANCE); *basename = resourcename(i->type->rtype, NMF_APPEARANCE);
@ -584,7 +584,7 @@ size_t size)
if (u->number && (u->faction == f || telepath_see || isbattle)) { if (u->number && (u->faction == f || telepath_see || isbattle)) {
const char *c = hp_status(u); const char *c = hp_status(u);
c = c ? locale_string(f->locale, c) : 0; c = c ? LOC(f->locale, c) : 0;
bytes = (int)strlcpy(bufp, ", ", size); bytes = (int)strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
@ -1956,7 +1956,7 @@ const char *trailinto(const region * r, const struct locale *lang)
if (r) { if (r) {
const char *tname = terrain_name(r); const char *tname = terrain_name(r);
strcat(strcpy(ref, tname), "_trail"); strcat(strcpy(ref, tname), "_trail");
s = locale_string(lang, ref); s = LOC(lang, ref);
if (s && *s) { if (s && *s) {
if (strstr(s, "%s")) if (strstr(s, "%s"))
return s; return s;
@ -2003,7 +2003,7 @@ static void eval_localize(struct opstack **stack, const void *userdata)
const struct faction *f = (const struct faction *)userdata; const struct faction *f = (const struct faction *)userdata;
const struct locale *lang = f ? f->locale : default_locale; const struct locale *lang = f ? f->locale : default_locale;
const char *c = (const char *)opop_v(stack); const char *c = (const char *)opop_v(stack);
c = locale_string(lang, c); c = LOC(lang, c);
opush_v(stack, strcpy(balloc(strlen(c) + 1), c)); opush_v(stack, strcpy(balloc(strlen(c) + 1), c));
} }

View file

@ -1,3 +1,4 @@
#include <platform.h>
#include <config.h> #include <config.h>
#include "reports.h" #include "reports.h"

View file

@ -66,7 +66,7 @@ void init_skills(const struct locale *lang) {
const char *skillname(skill_t sk, const struct locale *lang) const char *skillname(skill_t sk, const struct locale *lang)
{ {
if (skill_disabled[sk]) return 0; if (skill_disabled[sk]) return 0;
return locale_string(lang, mkname("skill", skillnames[sk])); return LOC(lang, mkname("skill", skillnames[sk]));
} }

View file

@ -74,10 +74,11 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c
unused_arg(obj); unused_arg(obj);
assert(typ == TYP_REGION); assert(typ == TYP_REGION);
if (curse_geteffect(c) > 0) { if (c->effect > 0) {
return msg_message("curseinfo::gooddream", "id", c->no); return msg_message("curseinfo::gooddream", "id", c->no);
} else {
return msg_message("curseinfo::baddream", "id", c->no);
} }
return msg_message("curseinfo::baddream", "id", c->no);
} }
static struct curse_type ct_gbdream = { static struct curse_type ct_gbdream = {
@ -99,7 +100,7 @@ static message *cinfo_magicstreet(const void *obj, objtype_t typ, const curse *
assert(typ == TYP_REGION); assert(typ == TYP_REGION);
/* Warnung vor Auflösung */ /* Warnung vor Auflösung */
if (c->duration <= 2) { if (c->duration >= 2) {
return msg_message("curseinfo::magicstreet", "id", c->no); return msg_message("curseinfo::magicstreet", "id", c->no);
} }
return msg_message("curseinfo::magicstreetwarn", "id", c->no); return msg_message("curseinfo::magicstreetwarn", "id", c->no);

View file

@ -1,4 +1,5 @@
#include <platform.h> #include <platform.h>
#include <eressea.h>
#include <kernel/config.h> #include <kernel/config.h>
#include <CuTest.h> #include <CuTest.h>
#include <stdio.h> #include <stdio.h>
@ -30,7 +31,7 @@ int RunAllTests(void)
int fail_count, flags = log_flags; int fail_count, flags = log_flags;
log_flags = LOG_FLUSH | LOG_CPERROR; log_flags = LOG_FLUSH | LOG_CPERROR;
kernel_init(); game_init();
/* self-test */ /* self-test */
RUN_TESTS(suite, tests); RUN_TESTS(suite, tests);
@ -70,6 +71,7 @@ int RunAllTests(void)
RUN_TESTS(suite, building); RUN_TESTS(suite, building);
RUN_TESTS(suite, spell); RUN_TESTS(suite, spell);
RUN_TESTS(suite, ally); RUN_TESTS(suite, ally);
RUN_TESTS(suite, messages);
/* gamecode */ /* gamecode */
RUN_TESTS(suite, battle); RUN_TESTS(suite, battle);
RUN_TESTS(suite, economy); RUN_TESTS(suite, economy);
@ -86,7 +88,7 @@ int RunAllTests(void)
log_flags = flags; log_flags = flags;
fail_count = suite->failCount; fail_count = suite->failCount;
CuSuiteDelete(suite); CuSuiteDelete(suite);
kernel_done(); game_done();
return fail_count; return fail_count;
} }

View file

@ -14,8 +14,10 @@
#include <kernel/spell.h> #include <kernel/spell.h>
#include <kernel/spellbook.h> #include <kernel/spellbook.h>
#include <kernel/terrain.h> #include <kernel/terrain.h>
#include <kernel/messages.h>
#include <util/functions.h> #include <util/functions.h>
#include <util/language.h> #include <util/language.h>
#include <util/message.h>
#include <util/log.h> #include <util/log.h>
#include <assert.h> #include <assert.h>
@ -81,14 +83,14 @@ test_create_terrain(const char * name, unsigned int flags)
building * test_create_building(region * r, const building_type * btype) building * test_create_building(region * r, const building_type * btype)
{ {
building * b = new_building(btype?btype:bt_find("castle"), r, default_locale); building * b = new_building(btype?btype:bt_get_or_create("castle"), r, default_locale);
b->size = b->type->maxsize>0?b->type->maxsize:1; b->size = b->type->maxsize>0?b->type->maxsize:1;
return b; return b;
} }
ship * test_create_ship(region * r, const ship_type * stype) ship * test_create_ship(region * r, const ship_type * stype)
{ {
ship * s = new_ship(stype?stype:st_find("boat"), r, default_locale); ship * s = new_ship(stype?stype:st_get_or_create("boat"), r, default_locale);
s->size = s->type->construction?s->type->construction->maxsize:1; s->size = s->type->construction?s->type->construction->maxsize:1;
return s; return s;
} }
@ -192,3 +194,22 @@ void test_create_world(void)
test_create_shiptype("boat"); test_create_shiptype("boat");
} }
message * test_get_last_message(message_list *msgs) {
struct mlist *iter = msgs->begin;
while (iter->next) {
iter = iter->next;
}
return iter->msg;
}
const char * test_get_messagetype(const message *msg) {
const char * name = msg->type->name;
if (strcmp(name, "missing_message") == 0) {
name = (const char *)msg->parameters[0].v;
}
else if (strcmp(name, "missing_feedback") == 0) {
name = (const char *)msg->parameters[3].v;
}
return name;
}

View file

@ -13,6 +13,8 @@ extern "C" {
struct faction; struct faction;
struct building; struct building;
struct ship; struct ship;
struct message;
struct message_list;
struct item_type; struct item_type;
struct building_type; struct building_type;
struct ship_type; struct ship_type;
@ -35,6 +37,8 @@ extern "C" {
int RunAllTests(void); int RunAllTests(void);
void test_translate_param(const struct locale *lang, param_t param, const char *text); void test_translate_param(const struct locale *lang, param_t param, const char *text);
const char * test_get_messagetype(const struct message *msg);
struct message * test_get_last_message(struct message_list *mlist);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -123,7 +123,7 @@ const char *locale_getstring(const locale * lang, const char *key)
return NULL; return NULL;
} }
const char *locale_string(const locale * lang, const char *key) const char *locale_string(const locale * lang, const char *key, bool warn)
{ {
assert(lang); assert(lang);
assert(key); assert(key);
@ -150,9 +150,11 @@ const char *locale_string(const locale * lang, const char *key)
if (find) { if (find) {
return find->str; return find->str;
} }
log_error("missing translation for \"%s\" in locale %s\n", key, lang->name); if (warn) {
log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name);
}
if (lang->fallback) { if (lang->fallback) {
return locale_string(lang->fallback, key); return locale_string(lang->fallback, key, warn);
} }
} }
return 0; return 0;
@ -262,7 +264,7 @@ void init_translations(const struct locale *lang, int ut, const char * (*string_
tokens = get_translations(lang, ut); tokens = get_translations(lang, ut);
for (i = 0; i != maxstrings; ++i) { for (i = 0; i != maxstrings; ++i) {
const char * s = string_cb(i); const char * s = string_cb(i);
const char * key = s ? locale_string(lang, s) : 0; const char * key = s ? locale_string(lang, s, false) : 0;
key = key ? key : s; key = key ? key : s;
if (key) { if (key) {
struct critbit_tree ** cb = (struct critbit_tree **)tokens; struct critbit_tree ** cb = (struct critbit_tree **)tokens;

View file

@ -18,6 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef MY_LOCALE_H #ifndef MY_LOCALE_H
#define MY_LOCALE_H #define MY_LOCALE_H
#include <platform.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -39,7 +42,7 @@ extern "C" {
const char *value); const char *value);
extern const char *locale_getstring(const struct locale *lang, extern const char *locale_getstring(const struct locale *lang,
const char *key); const char *key);
extern const char *locale_string(const struct locale *lang, const char *key); /* does fallback */ extern const char *locale_string(const struct locale *lang, const char *key, bool warn); /* does fallback */
extern unsigned int locale_index(const struct locale *lang); extern unsigned int locale_index(const struct locale *lang);
extern const char *locale_name(const struct locale *lang); extern const char *locale_name(const struct locale *lang);
@ -48,7 +51,7 @@ extern "C" {
extern void make_locales(const char *str); extern void make_locales(const char *str);
#define LOC(lang, s) (lang?locale_string(lang, s):s) #define LOC(lang, s) (lang?locale_string(lang, s, true):s)
extern struct locale *default_locale; extern struct locale *default_locale;
extern struct locale *locales; extern struct locale *locales;

View file

@ -146,7 +146,7 @@ message *msg_create(const struct message_type *mtype, variant args[])
return NULL; return NULL;
} }
msg->type = mtype; msg->type = mtype;
msg->parameters = (variant *) calloc(mtype->nparameters, sizeof(variant)); msg->parameters = (variant *)(mtype->nparameters ? calloc(mtype->nparameters, sizeof(variant)) : NULL);
msg->refcount = 1; msg->refcount = 1;
for (i = 0; i != mtype->nparameters; ++i) { for (i = 0; i != mtype->nparameters; ++i) {
msg->parameters[i] = copy_arg(mtype->types[i], args[i]); msg->parameters[i] = copy_arg(mtype->types[i], args[i]);

View file

@ -1,3 +1,4 @@
#include <platform.h>
#include <CuTest.h> #include <CuTest.h>
#include "unicode.h" #include "unicode.h"
#include <stdlib.h> #include <stdlib.h>
@ -10,14 +11,14 @@ static void test_unicode_tolower(CuTest * tc)
CuAssertIntEquals(tc, 0, unicode_utf8_tolower(buffer, sizeof(buffer), "HeLlO W0Rld")); CuAssertIntEquals(tc, 0, unicode_utf8_tolower(buffer, sizeof(buffer), "HeLlO W0Rld"));
CuAssertStrEquals(tc, "hello w0rld", buffer); CuAssertStrEquals(tc, "hello w0rld", buffer);
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
buffer[5]='X'; buffer[5] = 'X';
CuAssertIntEquals(tc, ENOMEM, unicode_utf8_tolower(buffer, 5, "HeLlO W0Rld")); CuAssertIntEquals(tc, ENOMEM, unicode_utf8_tolower(buffer, 5, "HeLlO W0Rld"));
CuAssertStrEquals(tc, "helloX", buffer); CuAssertStrEquals(tc, "helloX", buffer);
} }
CuSuite *get_unicode_suite(void) CuSuite *get_unicode_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_unicode_tolower); SUITE_ADD_TEST(suite, test_unicode_tolower);
return suite; return suite;
} }

View file

@ -1,4 +1,3 @@
#include <config.h>
#include <platform.h> #include <platform.h>
#include "vortex.h" #include "vortex.h"
@ -28,7 +27,7 @@ static dir_lookup *dir_name_lookup;
void register_special_direction(struct locale *lang, const char *name) void register_special_direction(struct locale *lang, const char *name)
{ {
const char *token = LOC(lang, name); const char *token = locale_string(lang, name, false);
if (token) { if (token) {
void **tokens = get_translations(lang, UT_SPECDIR); void **tokens = get_translations(lang, UT_SPECDIR);
@ -47,7 +46,7 @@ void register_special_direction(struct locale *lang, const char *name)
} }
} }
else { else {
log_error("no translation for spec_direction '%s' in locale '%s'\n", name, locale_name(lang)); log_debug("no translation for spec_direction '%s' in locale '%s'\n", name, locale_name(lang));
} }
} }