forked from github/server
Merge branch 'master' of github.com:ennorehling/eressea
This commit is contained in:
commit
4ea0e8b723
|
@ -41,7 +41,8 @@
|
|||
"nmr.timeout": 5,
|
||||
"nmr.removenewbie": false,
|
||||
"GiveRestriction": 3,
|
||||
"hunger.long": true,
|
||||
"hunger.long": false,
|
||||
"hunger.damage": "1d8+6",
|
||||
"init_spells": 0,
|
||||
"game.era": 2,
|
||||
"game.start": 184,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"include": [
|
||||
"config://res/races/goblin-3.xml",
|
||||
"config://res/races/wyrm.xml",
|
||||
"config://res/races/dragon.xml",
|
||||
"config://res/races/youngdragon.xml",
|
||||
"config://res/e3a/races.xml"
|
||||
"config://res/e3a/races.xml",
|
||||
"config://res/e3a/races/goblin.xml",
|
||||
"config://res/e3a/races/wyrm.xml",
|
||||
"config://res/e3a/races/dragon.xml",
|
||||
"config://res/e3a/races/youngdragon.xml"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -55,9 +55,6 @@ sendmail = True
|
|||
maxfiles = 30
|
||||
# write headers to file?
|
||||
writeheaders = True
|
||||
# write received files to database?
|
||||
tooldir = os.path.join(rootdir, 'orders-php')
|
||||
writedb = os.path.exists(tooldir)
|
||||
# reject all html email?
|
||||
rejecthtml = True
|
||||
|
||||
|
@ -235,13 +232,6 @@ def copy_orders(message, filename, sender, mtime):
|
|||
outfile.write(name + ": " + value + "\n")
|
||||
outfile.close()
|
||||
|
||||
if writedb:
|
||||
dirname, basename = os.path.split(filename)
|
||||
cli = os.path.join(tooldir, 'cli.php');
|
||||
dbname = os.path.join(dirname, 'orders.db')
|
||||
datestr = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))
|
||||
subprocess.call(['php', cli, '-d', dbname, 'insert', basename, sender, datestr])
|
||||
|
||||
found = False
|
||||
outfile = open(filename, "w")
|
||||
if message.is_multipart():
|
||||
|
@ -262,6 +252,7 @@ def copy_orders(message, filename, sender, mtime):
|
|||
charset = message.get_content_charset()
|
||||
logger.error("could not write text/plain message (charset=%s) for %s" % (charset, sender))
|
||||
outfile.close()
|
||||
|
||||
return found
|
||||
|
||||
# create a file, containing:
|
||||
|
@ -312,6 +303,9 @@ def accept(game, locale, stream, extend=None):
|
|||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n"
|
||||
|
||||
print('ACCEPT_MAIL=' + email)
|
||||
print('ACCEPT_FILE="' + filename + '"')
|
||||
|
||||
if not text_ok:
|
||||
warning = " (" + messages["error-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["multipart-" + locale], 76, 2) + "\n"
|
||||
|
|
|
@ -4,6 +4,13 @@ if [ -z $ERESSEA ] ; then
|
|||
echo "The ERESSEA environment variable is not set. Assuming $ERESSEA."
|
||||
fi
|
||||
GAME=$1
|
||||
|
||||
upload() {
|
||||
SRC="$1"
|
||||
DST=$(basename "$SRC")
|
||||
echo put "$SRC" "$DST" | cadaver "https://dav.box.com/dav/Eressea/game-$GAME/"
|
||||
}
|
||||
|
||||
if [ ! -d $ERESSEA/game-$GAME ]; then
|
||||
echo "No such game: game-$GAME."
|
||||
exit 1
|
||||
|
@ -26,7 +33,7 @@ fi
|
|||
if [ -e reports/reports.txt ] ; then
|
||||
echo "backup reports $TURN, game $GAME"
|
||||
tar cjf backup/$TURN-reports.tar.bz2 reports
|
||||
curl -s -n -T backup/$TURN-reports.tar.bz2 https://dav.box.com/dav/Eressea/game-$GAME/$TURN-reports.tar.bz2
|
||||
upload backup/$TURN-reports.tar.bz2
|
||||
fi
|
||||
files="data/$TURN.dat parteien.full parteien"
|
||||
if [ -e orders.$TURN ]; then
|
||||
|
@ -34,5 +41,5 @@ files="$files orders.$TURN"
|
|||
fi
|
||||
echo "backup turn $TURN, game $GAME, files: $files"
|
||||
tar cjf backup/$TURN.tar.bz2 $files
|
||||
curl -s -n -T backup/$TURN.tar.bz2 https://dav.box.com/dav/Eressea/game-$GAME/$TURN.tar.bz2
|
||||
#curl -s -n -T eressea.db https://dav.box.com/dav/Eressea/eressea.db
|
||||
upload backup/$TURN.tar.bz2
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ else
|
|||
mkdir -p orders.dir
|
||||
fi
|
||||
rm -f "orders.$TURN"
|
||||
find "orders.dir.$TURN" -maxdepth 1 -type f -printf "%T+\t%p\n" | sort | cut -f2 | while read -r
|
||||
find "orders.dir.$TURN" -maxdepth 1 -name "turn-*" -type f -printf "%T+\t%p\n" | sort | cut -f2 | while read -r
|
||||
do
|
||||
tr -d '\r' < "$REPLY" >> "orders.$TURN"
|
||||
done
|
||||
|
|
|
@ -45,9 +45,7 @@ class EPasswd:
|
|||
def load_database(self, file):
|
||||
conn = sqlite3.connect(file)
|
||||
c = conn.cursor()
|
||||
c.execute('SELECT MAX(turn) FROM factions')
|
||||
args = c.fetchone()
|
||||
for row in c.execute('SELECT no, email, password FROM factions WHERE turn=?', args):
|
||||
for row in c.execute('SELECT `no`, `email`, `password` FROM `faction`'):
|
||||
(no, email, passwd) = row
|
||||
self.set_data(baseconvert(no, 36), email, passwd)
|
||||
conn.close()
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
#!/bin/sh
|
||||
SCRIPT=$(readlink -f $0)
|
||||
cd $(dirname $SCRIPT)
|
||||
# example: orders-accept 2 de < mail.txt
|
||||
|
||||
lockfile -r3 -l120 orders.queue.lock
|
||||
python accept-orders.py "$@"
|
||||
rm -f orders.queue.lock
|
||||
game="$1"
|
||||
|
||||
[ -z "$ERESSEA" ] && ERESSEA="$HOME/eressea"
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
BIN=$(dirname "$SCRIPT")
|
||||
|
||||
LOCKFILE="$ERESSEA/game-$game/orders.queue.lock"
|
||||
set -e
|
||||
trap 'rm -f "$LOCKFILE"' EXIT
|
||||
|
||||
cd "$ERESSEA/game-$game"
|
||||
mkdir -p orders.dir
|
||||
cd orders.dir
|
||||
lockfile -r3 -l120 "$LOCKFILE"
|
||||
eval "$(python "$BIN/accept-orders.py" "$@")"
|
||||
rm -f "$LOCKFILE"
|
||||
filename=$(basename "$ACCEPT_FILE")
|
||||
email="$ACCEPT_MAIL"
|
||||
if [ -d "$ERESSEA/orders-php" ]
|
||||
then
|
||||
php "$ERESSEA/orders-php/cli.php" insert "$filename" "$email"
|
||||
fi
|
||||
|
|
|
@ -2937,13 +2937,6 @@
|
|||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error282" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error281" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
|
@ -3244,13 +3237,6 @@
|
|||
<arg name="target" type="region"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error241" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error240" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<entry spell="cerddor_destroymagic" level="8" />
|
||||
<entry spell="cerddorfumbleshield" level="5" />
|
||||
<entry spell="chaosrow" level="8" />
|
||||
<entry spell="clone" level="9" />
|
||||
<!-- <entry spell="clone" level="9" /> -->
|
||||
<entry spell="coldfront" level="8" />
|
||||
<entry spell="combatrust" level="6" />
|
||||
<entry spell="combat_speed" level="9" />
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<entry spell="readmind" level="7" />
|
||||
<entry spell="gooddreams" level="8" />
|
||||
<entry spell="illaundestroymagic" level="8" />
|
||||
<entry spell="clone" level="9" />
|
||||
<!-- <entry spell="clone" level="9" /> -->
|
||||
<entry spell="bad_dreams" level="10" />
|
||||
<entry spell="mindblast" level="11" />
|
||||
<entry spell="create_dreameye" level="14" />
|
||||
|
|
|
@ -79,13 +79,13 @@
|
|||
<!-- Traumbilder entwirren -->
|
||||
<resource name="aura" amount="6" cost="level"/>
|
||||
</spell>
|
||||
<!-- Seelenkopie, disabled version 3.20, Bug 1982
|
||||
<spell name="clone" rank="5">
|
||||
<!-- Seelenkopie -->
|
||||
<resource name="aura" amount="100" cost="fixed"/>
|
||||
<resource name="permaura" amount="20" cost="fixed"/>
|
||||
<resource name="dragonblood" amount="5" cost="fixed"/>
|
||||
<resource name="silk" amount="20" cost="fixed"/>
|
||||
</spell>
|
||||
</spell> -->
|
||||
<spell name="bad_dreams" rank="5" far="true">
|
||||
<!-- Schlechte Träume -->
|
||||
<resource name="aura" amount="90" cost="fixed"/>
|
||||
|
|
|
@ -782,7 +782,7 @@
|
|||
</race>
|
||||
<race name="halfling" magres="5" maxaura="1" regaura="1" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1" hp="18" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="hunger_damage" value="1d14+14"/>
|
||||
<param name="hunger_damage" value="1d10+7"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<entry spell="cerddorfumbleshield" level="5" />
|
||||
<entry spell="chaosrow" level="8" />
|
||||
<entry spell="chaossuction" level="14" />
|
||||
<entry spell="clone" level="9" />
|
||||
<!-- <entry spell="clone" level="9" /> -->
|
||||
<entry spell="coldfront" level="8" />
|
||||
<entry spell="cold_protection" level="3" />
|
||||
<entry spell="combatrust" level="6" />
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<entry spell="shadowknights" level="1" />
|
||||
<entry spell="sparkledream" level="1" />
|
||||
<entry spell="puttorest" level="2" />
|
||||
<entry spell="clone" level="9" />
|
||||
<!-- <entry spell="clone" level="9" /> -->
|
||||
<entry spell="create_roi" level="6" />
|
||||
<entry spell="earn_silver#illaun" level="1" />
|
||||
<entry spell="create_aots" level="6" />
|
||||
|
|
|
@ -314,7 +314,7 @@
|
|||
<resource name="aura" amount="10" cost="fixed"/>
|
||||
</spell>
|
||||
<spell name="analyse_object" rank="5" parameters="kc+" ship="true" variable="true" regiontarget="true" unittarget="false" buildingtarget="true" shiptarget="true">
|
||||
<resource name="aura" amount="3" cost="level"/>
|
||||
<resource name="aura" amount="3" cost="level"/>
|
||||
</spell>
|
||||
<spell name="destroy_magic" rank="2" parameters="kc+" los="true" ship="true" far="true" variable="true">
|
||||
<resource name="aura" amount="4" cost="level"/>
|
||||
|
@ -446,12 +446,13 @@
|
|||
<resource name="permaura" amount="10" cost="fixed"/>
|
||||
<resource name="toadslime" amount="1" cost="fixed"/>
|
||||
</spell>
|
||||
<spell name="clone" rank="5">
|
||||
<!-- Seelenkopie, disabled version 3.20, Bug 1982
|
||||
<spell name="clone" rank="5">
|
||||
<resource name="aura" amount="100" cost="fixed"/>
|
||||
<resource name="permaura" amount="20" cost="fixed"/>
|
||||
<resource name="dragonblood" amount="5" cost="fixed"/>
|
||||
<resource name="lifepotion" amount="5" cost="fixed"/>
|
||||
</spell>
|
||||
</spell> -->
|
||||
<spell name="drain_skills" rank="5" combat="2">
|
||||
<resource name="aura" amount="4" cost="fixed"/>
|
||||
</spell>
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="aquarian" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" shipspeed="yes" playerrace="yes" coastal="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
<skill name="trade" modifier="2"/>
|
||||
<skill name="armorer" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="3"/>
|
||||
<skill name="sailing" modifier="3"/>
|
||||
<skill name="roadwork" modifier="-1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="giantturtle"/>
|
||||
<familiar race="dolphin"/>
|
||||
<familiar race="giantturtle"/>
|
||||
<familiar race="dolphin"/>
|
||||
<familiar race="dolphin"/>
|
||||
<familiar race="kraken"/>
|
||||
</race>
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1" ?>
|
||||
<race name="cat" maxaura="1.000000" regaura="1.000000" recruitcost="90" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" defensemodifier="1" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-1"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
<skill name="catapult" modifier="-1"/>
|
||||
<skill name="herbalism" modifier="1"/>
|
||||
<skill name="armorer" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="sailing" modifier="-2"/>
|
||||
<skill name="espionage" modifier="2"/>
|
||||
<skill name="quarrying" modifier="-1"/>
|
||||
<skill name="roadwork" modifier="-1"/>
|
||||
<skill name="stealth" modifier="1"/>
|
||||
<skill name="perception" modifier="2"/>
|
||||
<skill name="taxation" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="lynx"/>
|
||||
<familiar race="dreamcat"/>
|
||||
<familiar race="lynx"/>
|
||||
<familiar race="songdragon"/>
|
||||
<familiar race="tiger"/>
|
||||
<familiar race="hellcat"/>
|
||||
</race>
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="demon" magres="15" maxaura="1.000000"
|
||||
regaura="1.250000" recruitcost="150" maintenance="10" weight="1000"
|
||||
capacity="540" speed="1.000000" hp="50" ac="2" damage="1d5"
|
||||
unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes"
|
||||
shapeshift="yes" giveperson="yes" giveunit="yes" getitem="yes"
|
||||
recruitethereal="yes" equipment="yes" healing="1.5">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="2"/>
|
||||
<skill name="trade" modifier="-3"/>
|
||||
<skill name="forestry" modifier="1"/>
|
||||
<skill name="herbalism" modifier="-3"/>
|
||||
<skill name="magic" modifier="1"/>
|
||||
<skill name="training" modifier="-3"/>
|
||||
<skill name="riding" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="melee" modifier="1"/>
|
||||
<skill name="sailing" modifier="-1"/>
|
||||
<skill name="polearm" modifier="1"/>
|
||||
<skill name="tactics" modifier="-1"/>
|
||||
<skill name="stealth" modifier="1"/>
|
||||
<skill name="entertainment" modifier="-3"/>
|
||||
<skill name="weaponsmithing" modifier="1"/>
|
||||
<skill name="cartmaking" modifier="-2"/>
|
||||
<skill name="perception" modifier="1"/>
|
||||
<skill name="taxation" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<attack type="5"/>
|
||||
<familiar race="imp"/>
|
||||
<familiar race="imp"/>
|
||||
<familiar race="ghost"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="wolf"/>
|
||||
<familiar race="imp"/>
|
||||
</race>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="dwarf" magres="5" maxaura="1.000000" regaura="0.500000" recruitcost="110" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="2"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
<skill name="trade" modifier="1"/>
|
||||
<skill name="forestry" modifier="-1"/>
|
||||
<skill name="catapult" modifier="2"/>
|
||||
<skill name="herbalism" modifier="-2"/>
|
||||
<skill name="magic" modifier="-2"/>
|
||||
<skill name="training" modifier="-2"/>
|
||||
<skill name="riding" modifier="-2"/>
|
||||
<skill name="armorer" modifier="2"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="melee" modifier="1"/>
|
||||
<skill name="sailing" modifier="-2"/>
|
||||
<skill name="quarrying" modifier="2"/>
|
||||
<skill name="roadwork" modifier="2"/>
|
||||
<skill name="stealth" modifier="-1"/>
|
||||
<skill name="entertainment" modifier="-1"/>
|
||||
<skill name="weaponsmithing" modifier="2"/>
|
||||
<skill name="taxation" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="tunnelworm"/>
|
||||
<familiar race="eagle"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="lynx"/>
|
||||
<familiar race="wolf"/>
|
||||
<familiar race="rat"/>
|
||||
</race>
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="elf" magres="10" maxaura="1.000000" regaura="1.250000" recruitcost="130" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="18" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-1"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="bow" modifier="2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
<skill name="catapult" modifier="-2"/>
|
||||
<skill name="herbalism" modifier="2"/>
|
||||
<skill name="magic" modifier="1"/>
|
||||
<skill name="training" modifier="1"/>
|
||||
<skill name="armorer" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="sailing" modifier="-1"/>
|
||||
<skill name="quarrying" modifier="-1"/>
|
||||
<skill name="roadwork" modifier="-1"/>
|
||||
<skill name="stealth" modifier="1"/>
|
||||
<skill name="perception" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="lynx"/>
|
||||
<familiar race="fairy"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="nymph"/>
|
||||
<familiar race="unicorn"/>
|
||||
<familiar race="imp"/>
|
||||
</race>
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="goblin" magres="-5" maxaura="1.000000"
|
||||
recruitcost="40" maintenance="10" weight="600"
|
||||
capacity="440" speed="1.000000" hp="16" damage="1d5"
|
||||
unarmedattack="-2" unarmeddefense="0" playerrace="yes" walk="yes"
|
||||
giveperson="yes" giveunit="yes" getitem="yes" equipment="yes"
|
||||
healing="2.0">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="building" modifier="1"/>
|
||||
<skill name="trade" modifier="-1"/>
|
||||
<skill name="catapult" modifier="1"/>
|
||||
<skill name="magic" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="-2"/>
|
||||
<skill name="sailing" modifier="-2"/>
|
||||
<skill name="roadwork" modifier="-2"/>
|
||||
<skill name="tactics" modifier="-2"/>
|
||||
<skill name="stealth" modifier="1"/>
|
||||
<skill name="entertainment" modifier="-1"/>
|
||||
<skill name="cartmaking" modifier="-1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="songdragon"/>
|
||||
<familiar race="imp"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="imp"/>
|
||||
</race>
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="halfling" magres="5" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="18" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="hunger_damage" value="1d14+14"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
<skill name="building" modifier="1"/>
|
||||
<skill name="trade" modifier="2"/>
|
||||
<skill name="catapult" modifier="-1"/>
|
||||
<skill name="herbalism" modifier="2"/>
|
||||
<skill name="training" modifier="-1"/>
|
||||
<skill name="riding" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="melee" modifier="-1"/>
|
||||
<skill name="sailing" modifier="-2"/>
|
||||
<skill name="polearm" modifier="-1"/>
|
||||
<skill name="espionage" modifier="1"/>
|
||||
<skill name="roadwork" modifier="1"/>
|
||||
<skill name="stealth" modifier="1"/>
|
||||
<skill name="entertainment" modifier="1"/>
|
||||
<skill name="cartmaking" modifier="2"/>
|
||||
<skill name="perception" modifier="1"/>
|
||||
<skill name="taxation" modifier="-1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="eagle"/>
|
||||
<familiar race="songdragon"/>
|
||||
<familiar race="eagle"/>
|
||||
<familiar race="rat"/>
|
||||
</race>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="human" maxaura="1.000000" regaura="1.000000" recruitcost="75" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="trade" modifier="1"/>
|
||||
<skill name="herbalism" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="1"/>
|
||||
<skill name="sailing" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="wolf"/>
|
||||
<familiar race="dreamcat"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="eagle"/>
|
||||
<familiar race="imp"/>
|
||||
</race>
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="insect" magres="5" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="24" ac="2" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="bow" modifier="-2"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
<skill name="trade" modifier="-1"/>
|
||||
<skill name="forestry" modifier="1"/>
|
||||
<skill name="herbalism" modifier="1"/>
|
||||
<skill name="training" modifier="-3"/>
|
||||
<skill name="riding" modifier="-3"/>
|
||||
<skill name="armorer" modifier="2"/>
|
||||
<skill name="melee" modifier="-1"/>
|
||||
<skill name="polearm" modifier="1"/>
|
||||
<skill name="roadwork" modifier="-1"/>
|
||||
<skill name="tactics" modifier="-1"/>
|
||||
<skill name="stealth" modifier="-1"/>
|
||||
<skill name="entertainment" modifier="-2"/>
|
||||
<skill name="perception" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="ghost"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="owl"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="tunnelworm"/>
|
||||
<familiar race="imp"/>
|
||||
</race>
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="orc" studyspeed="-5" magres="-5" maxaura="1.000000" regaura="1.000000" recruitcost="70" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="recruit_multi" value="0.5"/>
|
||||
<skill name="alchemy" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="building" modifier="1"/>
|
||||
<skill name="trade" modifier="-3"/>
|
||||
<skill name="forestry" modifier="1"/>
|
||||
<skill name="herbalism" modifier="-2"/>
|
||||
<skill name="magic" modifier="-1"/>
|
||||
<skill name="training" modifier="-1"/>
|
||||
<skill name="armorer" modifier="1"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="sailing" modifier="-1"/>
|
||||
<skill name="espionage" modifier="-1"/>
|
||||
<skill name="quarrying" modifier="1"/>
|
||||
<skill name="tactics" modifier="1"/>
|
||||
<skill name="entertainment" modifier="-2"/>
|
||||
<skill name="weaponsmithing" modifier="2"/>
|
||||
<skill name="cartmaking" modifier="-1"/>
|
||||
<skill name="taxation" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
<familiar race="goblin"/>
|
||||
<familiar race="ghost"/>
|
||||
<familiar race="imp"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="wolf"/>
|
||||
<familiar race="demon"/>
|
||||
</race>
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="troll" magres="10" maxaura="1.000000"
|
||||
regaura="1.000000" recruitcost="90" maintenance="10" weight="2000"
|
||||
capacity="1080" speed="1.000000" hp="30" ac="1" damage="1d5+3"
|
||||
unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes"
|
||||
giveperson="yes" giveunit="yes" getitem="yes" equipment="yes"
|
||||
healing="1.5">
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="2"/>
|
||||
<skill name="bow" modifier="-2"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
<skill name="catapult" modifier="2"/>
|
||||
<skill name="herbalism" modifier="-1"/>
|
||||
<skill name="training" modifier="-1"/>
|
||||
<skill name="riding" modifier="-2"/>
|
||||
<skill name="armorer" modifier="2"/>
|
||||
<skill name="shipcraft" modifier="-1"/>
|
||||
<skill name="melee" modifier="1"/>
|
||||
<skill name="sailing" modifier="-1"/>
|
||||
<skill name="espionage" modifier="-3"/>
|
||||
<skill name="quarrying" modifier="2"/>
|
||||
<skill name="roadwork" modifier="2"/>
|
||||
<skill name="tactics" modifier="-1"/>
|
||||
<skill name="stealth" modifier="-3"/>
|
||||
<skill name="entertainment" modifier="-1"/>
|
||||
<skill name="perception" modifier="-1"/>
|
||||
<skill name="taxation" modifier="1"/>
|
||||
<skill name="unarmed" modifier="-99"/>
|
||||
<attack type="1" damage="1d5+3"/>
|
||||
<familiar race="tunnelworm"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="rat"/>
|
||||
<familiar race="eagle"/>
|
||||
<familiar race="tunnelworm"/>
|
||||
<familiar race="wolf"/>
|
||||
</race>
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<race name="zombie" magres="20" maxaura="1.0" regaura="1.0"
|
||||
recruitcost="-1" maintenance="0" weight="1000" capacity="440" speed="1.000000"
|
||||
hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="no"
|
||||
walk="yes" shapeshift="no" giveperson="no" giveunit="no"
|
||||
getitem="no" equipment="yes" scarepeasants="yes"
|
||||
cansteal="no" unarmedguard="yes" noheal="yes"
|
||||
undead="yes" resistpierce="yes">
|
||||
<ai splitsize="1000" moverandom="yes" learn="yes" absorbpeasants="yes"/>
|
||||
<attack type="1" damage="1d5" />
|
||||
<attack type="5" />
|
||||
</race>
|
|
@ -105,7 +105,7 @@ msgid "massive_overload"
|
|||
msgstr "\"Die $ship($ship) ist zu stark überladen und wird stark beschädigt.\""
|
||||
|
||||
msgid "curseinfo::shipspeedup"
|
||||
msgstr "\"Die Winde scheinen dieses Schiff besonders zu beguenstigen. ($int36($id))\""
|
||||
msgstr "\"Die Winde scheinen dieses Schiff besonders zu begünstigen. ($int36($id))\""
|
||||
|
||||
msgid "error152"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit springt über Bord und ertrinkt.\""
|
||||
|
@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unbekannte Opti
|
|||
msgid "error131"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straßen bauen zu können, muß zuerst ein Tunnel errichtet werden.\""
|
||||
|
||||
msgid "error241"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen.\""
|
||||
|
||||
msgid "feedback_unit_not_found"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\""
|
||||
|
||||
|
@ -1002,7 +999,7 @@ msgid "battle_critical"
|
|||
msgstr "\"$int36($unit.id($unit))/$int($index) erzielt einen kritischen Treffer.\""
|
||||
|
||||
msgid "error_spell_on_ship_already"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf $ship($ship) liegt beeits ein Zauber.\""
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf $ship($ship) liegt bereits ein Zauber.\""
|
||||
|
||||
msgid "error228"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Nur normale Personen können Steuern eintreiben.\""
|
||||
|
@ -1119,7 +1116,7 @@ msgid "dissolve_units_4"
|
|||
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),\"zerfiel\", \"zerfielen\") zu Staub.\""
|
||||
|
||||
msgid "error281"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen welche Rasse soll der Jihad ausgerufen werden?\""
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Zielpartei muss die selbe Rasse haben.\""
|
||||
|
||||
msgid "error171"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Diesen Kampfzauber gibt es nicht.\""
|
||||
|
@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Es konnte kein
|
|||
msgid "error50"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafür.\""
|
||||
|
||||
msgid "error282"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen diese Rasse kann kein Jihad ausgerufen werden.\""
|
||||
|
||||
msgid "nmr_warning_final"
|
||||
msgstr "\"Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest.\""
|
||||
|
||||
|
|
|
@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unknown option.
|
|||
msgid "error131"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers.\""
|
||||
|
||||
msgid "error241"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The faction must be at least 81 weeks old to restart with a new race.\""
|
||||
|
||||
msgid "feedback_unit_not_found"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\""
|
||||
|
||||
|
@ -1119,7 +1116,7 @@ msgid "dissolve_units_4"
|
|||
msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) turned to dust.\""
|
||||
|
||||
msgid "error281"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - What race did you want the jihad to be against?\""
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The target faction must have the same race as yours.\""
|
||||
|
||||
msgid "error171"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - This combat spell does not exist.\""
|
||||
|
@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - No peasant coul
|
|||
msgid "error50"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this.\""
|
||||
|
||||
msgid "error282"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - You cannot start a jihad against this race.\""
|
||||
|
||||
msgid "nmr_warning_final"
|
||||
msgstr "\"Please send in orders for the next turn if you want to continue playing.\""
|
||||
|
||||
|
|
|
@ -16,12 +16,17 @@ local function tunnel_travelers(b)
|
|||
end
|
||||
|
||||
local function get_target(param)
|
||||
local ntargets = table.maxn(targets)
|
||||
if ntargets==0 then
|
||||
local ntargets = #targets
|
||||
if ntargets == 0 then
|
||||
eressea.log.error("Zero tunnel targets for [" .. param .. "]")
|
||||
return nil
|
||||
end
|
||||
local rn = math.fmod(rng_int(), ntargets)
|
||||
return targets[rn]
|
||||
local t = targets[rn + 1]
|
||||
if not t then
|
||||
eressea.log.error("NULL target for [" .. param .. "]" .. " at index " .. rn)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function tunnel_action(b, param)
|
||||
|
@ -50,7 +55,7 @@ function tunnels.init()
|
|||
local r, b
|
||||
for r in regions() do
|
||||
if r:get_key('tnnL') then
|
||||
targets[table.maxn(targets)+1] = r
|
||||
table.insert(targets, r)
|
||||
if (r:get_flag(0)) then
|
||||
-- target region is chaotic? nope.
|
||||
r:set_flag(0, false)
|
||||
|
@ -62,10 +67,11 @@ function tunnels.init()
|
|||
end
|
||||
for b in r.buildings do
|
||||
if b.type == 'portal' then
|
||||
buildings[table.maxn(buildings)+1] = b
|
||||
table.insert(buildings, b)
|
||||
end
|
||||
end
|
||||
end
|
||||
eressea.log.info("Found " .. #targets .. " tunnel targets")
|
||||
end
|
||||
|
||||
function tunnels.update()
|
||||
|
|
|
@ -15,7 +15,7 @@ local function wedding_travellers(b)
|
|||
local units = {}
|
||||
|
||||
for u in b.units do
|
||||
if u:get_flag('wdgt') then
|
||||
if u:get_key('wdgt') then
|
||||
units[u] = u
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
function dump_messages(f)
|
||||
for k, v in ipairs(f.messages) do
|
||||
print(v)
|
||||
end
|
||||
end
|
||||
|
||||
require 'tests.e2.movement'
|
||||
require 'tests.e2.astral'
|
||||
require 'tests.e2.spells'
|
||||
|
|
|
@ -216,21 +216,3 @@ function test_sawmill()
|
|||
assert_equal(6, u:get_item("log"))
|
||||
assert_equal(97, r:get_resource("tree"))
|
||||
end
|
||||
|
||||
function test_ent_guards_trees()
|
||||
local r = region.create(0, 0, "plain")
|
||||
r:set_resource("tree", 100)
|
||||
local u = unit.create(faction.create("human"), r)
|
||||
u:set_skill("mining", 1)
|
||||
local guard = unit.create(get_monsters(), r, 1, "ent")
|
||||
u:set_skill("forestry", 1)
|
||||
guard:clear_orders()
|
||||
u:clear_orders()
|
||||
|
||||
guard:add_order("BEWACHEN")
|
||||
u:add_order("MACHE HOLZ")
|
||||
process_orders()
|
||||
assert_equal(1, u:get_item("log"))
|
||||
process_orders()
|
||||
assert_equal(1, u:get_item("log"))
|
||||
end
|
||||
|
|
|
@ -54,11 +54,12 @@ static int read_seenspells(variant *var, void *owner, struct gamedata *data)
|
|||
READ_TOK(store, token, sizeof(token));
|
||||
while (token[0]) {
|
||||
spell *sp = find_spell(token);
|
||||
if (!sp) {
|
||||
log_info("read_seenspells: could not find spell '%s'\n", token);
|
||||
return AT_READ_FAIL;
|
||||
if (sp) {
|
||||
selist_push(&ql, sp);
|
||||
}
|
||||
else {
|
||||
log_info("read_seenspells: could not find spell '%s'\n", token);
|
||||
}
|
||||
selist_push(&ql, sp);
|
||||
READ_TOK(store, token, sizeof(token));
|
||||
}
|
||||
var->v = ql;
|
||||
|
@ -70,8 +71,8 @@ static bool cb_write_spell(void *data, void *more) {
|
|||
storage *store = (storage *)more;
|
||||
WRITE_TOK(store, sp->sname);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
write_seenspells(const variant *var, const void *owner, struct storage *store)
|
||||
{
|
||||
|
|
|
@ -160,7 +160,7 @@ static int tolua_make_island(lua_State * L)
|
|||
int y = (int)tolua_tonumber(L, 2, 0);
|
||||
int s = (int)tolua_tonumber(L, 3, 0);
|
||||
|
||||
s = build_island_e3(x, y, s, NULL, 0);
|
||||
s = build_island(x, y, s, NULL, 0);
|
||||
lua_pushinteger(L, s);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -760,7 +760,7 @@ static int tolua_unit_has_attrib(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_unit_get_flag(lua_State * L)
|
||||
static int tolua_unit_get_key(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
|
@ -769,7 +769,7 @@ static int tolua_unit_get_flag(lua_State * L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_unit_set_flag(lua_State * L)
|
||||
static int tolua_unit_set_key(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
|
@ -784,6 +784,28 @@ static int tolua_unit_set_flag(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tolua_unit_get_flag(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, NULL);
|
||||
int bit = (int)tolua_tonumber(L, 2, 0);
|
||||
|
||||
lua_pushboolean(L, (self->flags & (1 << bit)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tolua_unit_set_flag(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, NULL);
|
||||
int bit = (int)tolua_tonumber(L, 2, 0);
|
||||
int set = tolua_toboolean(L, 3, 1);
|
||||
|
||||
if (set)
|
||||
self->flags |= (1 << bit);
|
||||
else
|
||||
self->flags &= ~(1 << bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tolua_unit_get_weight(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
|
@ -959,6 +981,8 @@ void tolua_unit_open(lua_State * L)
|
|||
tolua_function(L, TOLUA_CAST "has_attrib", tolua_unit_has_attrib);
|
||||
|
||||
/* key-attributes for named flags: */
|
||||
tolua_function(L, TOLUA_CAST "set_key", tolua_unit_set_key);
|
||||
tolua_function(L, TOLUA_CAST "get_key", tolua_unit_get_key);
|
||||
tolua_function(L, TOLUA_CAST "set_flag", tolua_unit_set_flag);
|
||||
tolua_function(L, TOLUA_CAST "get_flag", tolua_unit_get_flag);
|
||||
tolua_variable(L, TOLUA_CAST "guard", tolua_unit_get_guard,
|
||||
|
|
|
@ -100,7 +100,7 @@ struct locale *crtag_locale(void) {
|
|||
static int config;
|
||||
if (config_changed(&config)) {
|
||||
const char *lname = config_get("creport.tags");
|
||||
lang = get_locale(lname ? lname : "de");
|
||||
lang = lname ? get_locale(lname) : default_locale;
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
@ -108,8 +108,8 @@ struct locale *crtag_locale(void) {
|
|||
static const char *crtag(const char *key)
|
||||
{
|
||||
const char *result;
|
||||
result = LOC(crtag_locale(), key);
|
||||
return result;
|
||||
result = locale_string(crtag_locale(), key, false);
|
||||
return result ? result : key;
|
||||
}
|
||||
/*
|
||||
* translation table
|
||||
|
@ -849,11 +849,17 @@ void cr_output_unit(stream *out, const faction * f,
|
|||
pzTmp = get_racename(u->attribs);
|
||||
if (pzTmp) {
|
||||
const char *pzRace = locale_string(lang, mkname("race", pzTmp), false);
|
||||
pzTmp = pzRace ? translate(pzRace, LOC(lang, pzRace)) : pzTmp;
|
||||
stream_printf(out, "\"%s\";Typ\n", pzTmp);
|
||||
if (pzRace) {
|
||||
pzTmp = pzRace;
|
||||
}
|
||||
pzRace = translate(pzTmp, locale_string(lang, pzTmp, false));
|
||||
if (!pzRace) {
|
||||
pzRace = pzTmp;
|
||||
}
|
||||
stream_printf(out, "\"%s\";Typ\n", pzRace);
|
||||
if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) {
|
||||
pzRace = rc_name_s(u_race(u), NAME_PLURAL);
|
||||
stream_printf(out, "\"%s\";wahrerTyp\n", pzTmp);
|
||||
stream_printf(out, "\"%s\";wahrerTyp\n", pzRace);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -548,7 +548,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
|||
return;
|
||||
}
|
||||
if (has_skill(u, SK_ALCHEMY)) {
|
||||
if (count_skill(u->faction, SK_ALCHEMY) + n > skill_limit(u->faction, SK_ALCHEMY)) {
|
||||
if (faction_count_skill(u->faction, SK_ALCHEMY) + n > faction_skill_limit(u->faction, SK_ALCHEMY)) {
|
||||
cmistake(u, ord, 156, MSG_EVENT);
|
||||
return;
|
||||
}
|
||||
|
|
31
src/gamedb.c
31
src/gamedb.c
|
@ -9,9 +9,27 @@
|
|||
#include "kernel/faction.h"
|
||||
#include "kernel/db/driver.h"
|
||||
|
||||
#include "util/strings.h"
|
||||
|
||||
static int generate_factions(void *data, db_faction *results, int nresults)
|
||||
{
|
||||
int i;
|
||||
faction **iter = (faction **)data;
|
||||
for (i = 0; *iter && i != nresults; ++i) {
|
||||
faction *f = *iter;
|
||||
const char *pwhash;
|
||||
results[i].p_uid = &f->uid;
|
||||
results[i].no = f->no;
|
||||
results[i].email = faction_getemail(f);
|
||||
pwhash = faction_getpassword(f);
|
||||
str_strlcpy(results[i].pwhash, pwhash ? pwhash : "", sizeof(results[i].pwhash));
|
||||
*iter = f->next;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int gamedb_update(void)
|
||||
{
|
||||
faction *f;
|
||||
int err;
|
||||
const char *dbname;
|
||||
|
||||
|
@ -19,14 +37,9 @@ int gamedb_update(void)
|
|||
|
||||
err = db_driver_open(DB_GAME, dbname);
|
||||
if (err == 0) {
|
||||
for (f = factions; f; f = f->next) {
|
||||
int uid = db_driver_faction_save(f->uid, f->no, turn,
|
||||
faction_getemail(f),
|
||||
faction_getpassword(f));
|
||||
if (uid > 0) {
|
||||
f->uid = uid;
|
||||
}
|
||||
}
|
||||
faction *list = factions;
|
||||
db_driver_update_factions(generate_factions, &list);
|
||||
db_driver_compact(turn);
|
||||
db_driver_close(DB_GAME);
|
||||
}
|
||||
return err;
|
||||
|
|
44
src/give.c
44
src/give.c
|
@ -299,7 +299,7 @@ static bool can_give_men(const unit *u, const unit *dst, order *ord, message **m
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool rule_transfermen(void)
|
||||
bool rule_transfermen(void)
|
||||
{
|
||||
int rule = config_get_int("rules.transfermen", 1);
|
||||
return rule != 0;
|
||||
|
@ -391,7 +391,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
|||
}
|
||||
|
||||
if (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY)) {
|
||||
int k = count_skill(u2->faction, SK_ALCHEMY);
|
||||
int k = faction_count_skill(u2->faction, SK_ALCHEMY);
|
||||
|
||||
/* Falls die Zieleinheit keine Alchemisten sind, werden sie nun
|
||||
* welche. */
|
||||
|
@ -408,7 +408,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
|
|||
|
||||
/* wird das Alchemistenmaximum ueberschritten ? */
|
||||
|
||||
if (k > skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
if (k > faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
error = 156;
|
||||
}
|
||||
}
|
||||
|
@ -472,9 +472,23 @@ message * disband_men(int n, unit * u, struct order *ord) {
|
|||
return msg_message("give_person_peasants", "unit amount", u, n);
|
||||
}
|
||||
|
||||
int give_unit_allowed(const unit * u)
|
||||
{
|
||||
if (unit_has_cursed_item(u)) {
|
||||
return 78;
|
||||
}
|
||||
if (fval(u, UFL_HERO)) {
|
||||
return 75;
|
||||
}
|
||||
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
|
||||
return 74;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void give_unit(unit * u, unit * u2, order * ord)
|
||||
{
|
||||
int maxt = max_transfers();
|
||||
int err, maxt = max_transfers();
|
||||
|
||||
assert(u);
|
||||
if (!rule_transfermen() && u2 && u->faction != u2->faction) {
|
||||
|
@ -482,17 +496,9 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
return;
|
||||
}
|
||||
|
||||
if (unit_has_cursed_item(u)) {
|
||||
cmistake(u, ord, 78, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fval(u, UFL_HERO)) {
|
||||
cmistake(u, ord, 75, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
|
||||
cmistake(u, ord, 74, MSG_COMMERCE);
|
||||
err = give_unit_allowed(u);
|
||||
if (err != 0) {
|
||||
cmistake(u, ord, err, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -586,8 +592,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
}
|
||||
}
|
||||
if (has_skill(u, SK_MAGIC)) {
|
||||
if (count_skill(u2->faction, SK_MAGIC) + u->number >
|
||||
skill_limit(u2->faction, SK_MAGIC)) {
|
||||
if (faction_count_skill(u2->faction, SK_MAGIC) + u->number >
|
||||
faction_skill_limit(u2->faction, SK_MAGIC)) {
|
||||
cmistake(u, ord, 155, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
@ -597,8 +603,8 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
}
|
||||
}
|
||||
if (has_skill(u, SK_ALCHEMY)
|
||||
&& count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||||
skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
&& faction_count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||||
faction_skill_limit(u2->faction, SK_ALCHEMY)) {
|
||||
cmistake(u, ord, 156, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -29,10 +29,12 @@ extern "C" {
|
|||
struct message * disband_men(int n, struct unit * u, struct order *ord);
|
||||
struct message * give_men(int n, struct unit *u, struct unit *u2,
|
||||
struct order *ord);
|
||||
int give_unit_allowed(const struct unit * u);
|
||||
void give_unit(struct unit *u, struct unit *u2, struct order *ord);
|
||||
void give_cmd(struct unit * u, struct order * ord);
|
||||
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
|
||||
bool can_give_to(struct unit *u, struct unit *u2);
|
||||
bool rule_transfermen(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1143,7 +1143,7 @@ static void handlekey(state * st, int c)
|
|||
else {
|
||||
n = minpop;
|
||||
}
|
||||
build_island_e3(nx, ny, n, NULL, 0);
|
||||
build_island(nx, ny, n, NULL, 0);
|
||||
st->modified = 1;
|
||||
st->wnd_info->update |= 1;
|
||||
st->wnd_status->update |= 1;
|
||||
|
|
|
@ -572,7 +572,7 @@ static int build_limited(unit * u, const construction * con, int completed, int
|
|||
}
|
||||
/* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische)
|
||||
* Talente */
|
||||
if (skill_limit(u->faction, con->skill) == INT_MAX) {
|
||||
if (faction_skill_limit(u->faction, con->skill) == INT_MAX) {
|
||||
const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
|
||||
item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
|
||||
int i = itm ? itm->number : 0;
|
||||
|
@ -729,8 +729,9 @@ static int build_stages(unit *u, const building_type *btype, int built, int n, i
|
|||
}
|
||||
else {
|
||||
/* err is the amount we built of this stage */
|
||||
built += err;
|
||||
made += err;
|
||||
if (err != con->maxsize && con->maxsize > 0) {
|
||||
if (con->maxsize > 0 && built < con->maxsize) {
|
||||
/* we did not finish the stage, can quit here */
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,28 @@ static void test_build_building_stages(CuTest *tc) {
|
|||
item_type *it_stone;
|
||||
unit *u;
|
||||
|
||||
test_setup();
|
||||
init_resources();
|
||||
it_stone = test_create_itemtype("stone");
|
||||
btype = setup_castle(it_stone);
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u->building = test_create_building(u->region, btype);
|
||||
u->building->size = 1;
|
||||
set_level(u, SK_BUILDING, 2);
|
||||
i_change(&u->items, it_stone, 4);
|
||||
build_building(u, btype, -1, INT_MAX, NULL);
|
||||
CuAssertPtrNotNull(tc, u->building);
|
||||
CuAssertIntEquals(tc, 3, u->building->size);
|
||||
CuAssertIntEquals(tc, 2, i_get(u->items, it_stone));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_build_building_stage_continue(CuTest *tc) {
|
||||
building_type *btype;
|
||||
item_type *it_stone;
|
||||
unit *u;
|
||||
|
||||
test_setup();
|
||||
init_resources();
|
||||
it_stone = test_create_itemtype("stone");
|
||||
|
@ -450,6 +472,7 @@ CuSuite *get_build_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_build_with_potion);
|
||||
SUITE_ADD_TEST(suite, test_build_building_success);
|
||||
SUITE_ADD_TEST(suite, test_build_building_stages);
|
||||
SUITE_ADD_TEST(suite, test_build_building_stage_continue);
|
||||
SUITE_ADD_TEST(suite, test_build_building_with_golem);
|
||||
SUITE_ADD_TEST(suite, test_build_building_no_materials);
|
||||
SUITE_ADD_TEST(suite, test_build_destroy_cmd);
|
||||
|
|
|
@ -47,19 +47,28 @@ static void test_save_load_order(CuTest *tc) {
|
|||
|
||||
static void test_update_faction(CuTest *tc) {
|
||||
faction *f;
|
||||
int uid;
|
||||
int err;
|
||||
dbrow_id id;
|
||||
|
||||
test_setup();
|
||||
db_driver_open(DB_GAME, NULL);
|
||||
f = test_create_faction(NULL);
|
||||
uid = db_driver_faction_save(f->uid, f->no, 0,
|
||||
CuAssertIntEquals(tc, 0, f->uid);
|
||||
id = 0;
|
||||
err = db_driver_faction_save(&id, f->no,
|
||||
faction_getemail(f),
|
||||
faction_getpassword(f));
|
||||
f->uid = uid;
|
||||
uid = db_driver_faction_save(f->uid, f->no, 0,
|
||||
CuAssertIntEquals(tc, 0, err);
|
||||
CuAssertTrue(tc, 0 != id);
|
||||
f->uid = (int)id;
|
||||
db_driver_close(DB_GAME);
|
||||
|
||||
db_driver_open(DB_GAME, NULL);
|
||||
err = db_driver_faction_save(&id, f->no,
|
||||
faction_getemail(f),
|
||||
faction_getpassword(f));
|
||||
CuAssertIntEquals(tc, f->uid, uid);
|
||||
CuAssertIntEquals(tc, 0, err);
|
||||
CuAssertIntEquals(tc, f->uid, id);
|
||||
db_driver_close(DB_GAME);
|
||||
test_teardown();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct order_data;
|
||||
|
||||
|
@ -17,6 +18,17 @@ int db_driver_open(database_t db, const char *dbname);
|
|||
void db_driver_close(database_t db);
|
||||
dbrow_id db_driver_order_save(const char *str);
|
||||
struct order_data *db_driver_order_load(dbrow_id id);
|
||||
dbrow_id db_driver_faction_save(dbrow_id id, int no, int turn, const char *email, const char *password);
|
||||
dbrow_id db_driver_string_save(const char *s);
|
||||
const char *db_driver_string_load(dbrow_id id, size_t *size);
|
||||
void db_driver_compact(int turn);
|
||||
|
||||
typedef struct db_faction {
|
||||
int *p_uid;
|
||||
int no;
|
||||
const char *email;
|
||||
char pwhash[128];
|
||||
} db_faction;
|
||||
|
||||
typedef int (*db_faction_generator)(void *, db_faction *, int);
|
||||
int db_driver_update_factions(db_faction_generator gen, void *data);
|
||||
int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const char *password);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <kernel/config.h>
|
||||
|
||||
#include <util/log.h>
|
||||
#include <util/base36.h>
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
|
@ -95,68 +96,113 @@ dbrow_id db_driver_order_save(const char *str) {
|
|||
return (dbrow_id)id;
|
||||
}
|
||||
|
||||
|
||||
dbrow_id db_driver_faction_save(dbrow_id id, int no, int turn, const char *email, const char *password)
|
||||
int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const char *password)
|
||||
{
|
||||
sqlite3_int64 row_id;
|
||||
dbrow_id id = *p_id;
|
||||
int err;
|
||||
char dbno[4];
|
||||
size_t len;
|
||||
const char *str;
|
||||
sqlite3_stmt *stmt = (id > 0) ? g_stmt_update_faction : g_stmt_insert_faction;
|
||||
|
||||
assert(g_game_db);
|
||||
if (id != 0) {
|
||||
int rows;
|
||||
|
||||
err = sqlite3_reset(g_stmt_update_faction);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_int(g_stmt_update_faction, 1, no);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_int(g_stmt_update_faction, 2, turn);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_text(g_stmt_update_faction, 3, email, -1, SQLITE_STATIC);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_text(g_stmt_update_faction, 4, password, -1, SQLITE_STATIC);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_int(g_stmt_update_faction, 5, id);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_step(g_stmt_update_faction);
|
||||
assert(err == SQLITE_DONE);
|
||||
rows = sqlite3_changes(g_game_db);
|
||||
if (rows != 0) {
|
||||
return id;
|
||||
}
|
||||
err = sqlite3_reset(stmt);
|
||||
if (err != SQLITE_OK) return err;
|
||||
str = itoa36(no);
|
||||
len = strlen(str);
|
||||
assert(len <= 4);
|
||||
memcpy(dbno, str, len);
|
||||
err = sqlite3_bind_text(stmt, 1, dbno, len, SQLITE_STATIC);
|
||||
if (err != SQLITE_OK) return err;
|
||||
err = sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC);
|
||||
if (err != SQLITE_OK) return err;
|
||||
err = sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC);
|
||||
if (err != SQLITE_OK) return err;
|
||||
|
||||
if (id > 0) {
|
||||
err = sqlite3_bind_int(stmt, 4, id);
|
||||
if (err != SQLITE_OK) return err;
|
||||
}
|
||||
err = sqlite3_reset(g_stmt_insert_faction);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_int(g_stmt_insert_faction, 1, no);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_int(g_stmt_insert_faction, 2, turn);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_text(g_stmt_insert_faction, 3, email, -1, SQLITE_STATIC);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_bind_text(g_stmt_insert_faction, 4, password, -1, SQLITE_STATIC);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_step(g_stmt_insert_faction);
|
||||
assert(err == SQLITE_DONE);
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) return err;
|
||||
ERRNO_CHECK();
|
||||
|
||||
row_id = sqlite3_last_insert_rowid(g_game_db);
|
||||
assert(row_id>0 && row_id <= UINT_MAX);
|
||||
return (dbrow_id)row_id;
|
||||
if (id <= 0) {
|
||||
sqlite3_int64 row_id;
|
||||
row_id = sqlite3_last_insert_rowid(g_game_db);
|
||||
assert(row_id > 0 && row_id <= UINT_MAX);
|
||||
*p_id = (dbrow_id)row_id;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int db_driver_update_factions(db_faction_generator gen, void *data)
|
||||
{
|
||||
db_faction results[32];
|
||||
int num, err;
|
||||
|
||||
err = sqlite3_exec(g_game_db, "BEGIN TRANSACTION", NULL, NULL, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_exec(g_game_db, "DELETE FROM `faction`", NULL, NULL, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
sqlite3_exec(g_game_db, "ROLLBACK", NULL, NULL, NULL);
|
||||
return err;
|
||||
}
|
||||
num = gen(data, results, 32);
|
||||
while (num > 0) {
|
||||
int i;
|
||||
for (i = 0; i != num; ++i) {
|
||||
db_faction *dbf = results + i;
|
||||
dbrow_id id = (dbrow_id)*dbf->p_uid;
|
||||
err = db_driver_faction_save(&id, dbf->no, dbf->email, dbf->pwhash);
|
||||
if (err != SQLITE_OK) {
|
||||
sqlite3_exec(g_game_db, "ROLLBACK", NULL, NULL, NULL);
|
||||
return err;
|
||||
}
|
||||
assert(id > 0 && id <= INT_MAX);
|
||||
*dbf->p_uid = (int)id;
|
||||
}
|
||||
num = gen(data, results, 32);
|
||||
}
|
||||
err = sqlite3_exec(g_game_db, "COMMIT", NULL, NULL, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cb_int_col(void *data, int ncols, char **text, char **name) {
|
||||
int *p_int = (int *)data;
|
||||
*p_int = atoi(text[0]);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int db_open_game(const char *dbname) {
|
||||
int err;
|
||||
int err, version = 0;
|
||||
|
||||
err = sqlite3_open(dbname, &g_game_db);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS factions (id INTEGER PRIMARY KEY, no INTEGER NOT NULL, email VARCHAR(128), password VARCHAR(128), turn INTEGER NOT NULL)", NULL, NULL, NULL);
|
||||
|
||||
err = sqlite3_exec(g_game_db, "PRAGMA user_version", cb_int_col, &version, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_prepare_v2(g_game_db, "UPDATE factions SET no=?, turn=?, email=?, password=? WHERE id=?", -1, &g_stmt_update_faction, NULL);
|
||||
if (version < 1) {
|
||||
/* drop deprecated table */
|
||||
err = sqlite3_exec(g_game_db, "DROP TABLE IF EXISTS `factions`", NULL, NULL, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
}
|
||||
if (version < 2) {
|
||||
/* install schema version 2: */
|
||||
err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS `faction` (`id` INTEGER PRIMARY KEY, `no` CHAR(4) NOT NULL UNIQUE, `email` VARCHAR(128), `password` VARCHAR(128))", NULL, NULL, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_exec(g_game_db, "PRAGMA user_version = 2", NULL, NULL, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
}
|
||||
/* create prepared statments: */
|
||||
err = sqlite3_prepare_v2(g_game_db, "INSERT INTO `faction` (`no`, `email`, `password`, `id`) VALUES (?,?,?,?)", -1, &g_stmt_update_faction, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
err = sqlite3_prepare_v2(g_game_db, "INSERT INTO factions (no, turn, email, password) VALUES (?,?,?,?)", -1, &g_stmt_insert_faction, NULL);
|
||||
err = sqlite3_prepare_v2(g_game_db, "INSERT INTO `faction` (`no`, `email`, `password`) VALUES (?,?,?)", -1, &g_stmt_insert_faction, NULL);
|
||||
assert(err == SQLITE_OK);
|
||||
|
||||
ERRNO_CHECK();
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int db_open_swap(const char *dbname) {
|
||||
|
@ -303,3 +349,13 @@ const char *db_driver_string_load(dbrow_id id, size_t *size) {
|
|||
ERRNO_CHECK();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void db_driver_compact(int turn)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* repack database: */
|
||||
err = sqlite3_exec(g_game_db, "VACUUM", 0, 0, 0);
|
||||
assert(err == SQLITE_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@ static bool equip_callback(unit *u, const char *eqname, int mask) {
|
|||
|
||||
static void test_equipment(CuTest * tc)
|
||||
{
|
||||
callbacks.equip_unit = equip_callback;
|
||||
unit * u;
|
||||
|
||||
test_setup();
|
||||
callbacks.equip_unit = equip_callback;
|
||||
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
CuAssertIntEquals(tc, true, equip_unit_mask(u, "hodor", EQUIP_ALL));
|
||||
|
|
|
@ -281,6 +281,7 @@ unit *addplayer(region * r, faction * f)
|
|||
assert(f->units == NULL);
|
||||
faction_setorigin(f, 0, r->x, r->y);
|
||||
u = create_unit(r, f, 1, f->race, 0, NULL, NULL);
|
||||
u->status = ST_FLEE;
|
||||
u->thisorder = default_order(f->locale);
|
||||
unit_addorder(u, copy_order(u->thisorder));
|
||||
name = config_get("rules.equip_first");
|
||||
|
@ -609,7 +610,7 @@ static int allied_skillcount(const faction * f, skill_t sk)
|
|||
|
||||
for (qi = 0; members; selist_advance(&members, &qi, 1)) {
|
||||
faction *m = (faction *)selist_get(members, qi);
|
||||
num += count_skill(m, sk);
|
||||
num += faction_count_skill(m, sk);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
@ -623,7 +624,7 @@ static int allied_skilllimit(const faction * f, skill_t sk)
|
|||
return value;
|
||||
}
|
||||
|
||||
int count_skill(faction * f, skill_t sk)
|
||||
int faction_count_skill(faction * f, skill_t sk)
|
||||
{
|
||||
int n = 0;
|
||||
unit *u;
|
||||
|
@ -638,7 +639,7 @@ int count_skill(faction * f, skill_t sk)
|
|||
return n;
|
||||
}
|
||||
|
||||
int skill_limit(faction * f, skill_t sk)
|
||||
int faction_skill_limit(const faction * f, skill_t sk)
|
||||
{
|
||||
int m = INT_MAX;
|
||||
int al = allied_skilllimit(f, sk);
|
||||
|
|
|
@ -161,8 +161,8 @@ extern "C" {
|
|||
struct spellbook * faction_get_spellbook(struct faction *f);
|
||||
|
||||
/* skills */
|
||||
int skill_limit(struct faction *f, skill_t sk);
|
||||
int count_skill(struct faction *f, skill_t sk);
|
||||
int faction_skill_limit(const struct faction *f, skill_t sk);
|
||||
int faction_count_skill(struct faction *f, skill_t sk);
|
||||
bool faction_id_is_unused(int);
|
||||
|
||||
#define COUNT_MONSTERS 0x01
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
static void test_destroyfaction_allies(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
|
@ -211,6 +212,26 @@ static void test_max_migrants(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_skill_limit(CuTest *tc) {
|
||||
faction *f;
|
||||
|
||||
test_setup();
|
||||
f = test_create_faction(NULL);
|
||||
CuAssertIntEquals(tc, INT_MAX, faction_skill_limit(f, SK_ENTERTAINMENT));
|
||||
CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_ALCHEMY));
|
||||
config_set_int("rules.maxskills.alchemy", 4);
|
||||
CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_ALCHEMY));
|
||||
CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 3, max_magicians(f));
|
||||
config_set_int("rules.maxskills.magic", 4);
|
||||
CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 4, max_magicians(f));
|
||||
f->race = test_create_race(racenames[RC_ELF]);
|
||||
CuAssertIntEquals(tc, 5, faction_skill_limit(f, SK_MAGIC));
|
||||
CuAssertIntEquals(tc, 5, max_magicians(f));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_valid_race(CuTest *tc) {
|
||||
race * rc1, *rc2;
|
||||
faction *f;
|
||||
|
@ -334,6 +355,7 @@ CuSuite *get_faction_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_addplayer);
|
||||
SUITE_ADD_TEST(suite, test_max_migrants);
|
||||
SUITE_ADD_TEST(suite, test_skill_limit);
|
||||
SUITE_ADD_TEST(suite, test_addfaction);
|
||||
SUITE_ADD_TEST(suite, test_remove_empty_factions);
|
||||
SUITE_ADD_TEST(suite, test_destroyfaction_allies);
|
||||
|
|
|
@ -43,8 +43,10 @@
|
|||
#define FAMILIAR_FIXSPELLBOOK_VERSION 365 /* familiar spells are fixed */
|
||||
#define FIX_STARTLEVEL_VERSION 366 /* fixing resource startlevels */
|
||||
#define FIX_RES_BASE_VERSION 367 /* fixing resource base */
|
||||
#define FIX_CLONES_VERSION 368 /* dissolve clones */
|
||||
#define FIX_MIGRANT_AURA_VERSION 369 /* bug 2585, migrants with aura */
|
||||
|
||||
#define RELEASE_VERSION FIX_RES_BASE_VERSION /* current datafile */
|
||||
#define RELEASE_VERSION FIX_MIGRANT_AURA_VERSION /* current datafile */
|
||||
#define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */
|
||||
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||
|
||||
|
@ -65,6 +67,4 @@ void gamedata_close(gamedata *data);
|
|||
gamedata *gamedata_open(const char *filename, const char *mode, int version);
|
||||
int gamedata_openfile(gamedata *data, const char *filename, const char *mode, int version);
|
||||
|
||||
#define STREAM_VERSION 2 /* internal encoding of binary files */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1395,6 +1395,72 @@ static void fix_fam_triggers(unit *u) {
|
|||
}
|
||||
}
|
||||
|
||||
static void fix_clone(unit *uc) {
|
||||
attrib * a;
|
||||
assert(uc);
|
||||
assert(uc->number > 0);
|
||||
ADDMSG(&uc->faction->msgs, msg_message("dissolve_units_5",
|
||||
"unit region number race", uc, uc->region, uc->number, u_race(uc)));
|
||||
a_removeall(&uc->attribs, &at_clonemage);
|
||||
a = a_new(&at_unitdissolve);
|
||||
a->data.ca[0] = 0;
|
||||
a->data.ca[1] = 100;
|
||||
a_add(&uc->attribs, a);
|
||||
}
|
||||
|
||||
static void fix_clone_mage(unit *um, const item_type *itype) {
|
||||
i_change(&um->items, itype, 1);
|
||||
change_maxspellpoints(um, 20);
|
||||
a_removeall(&um->attribs, &at_clone);
|
||||
}
|
||||
|
||||
static void fix_clones(void) {
|
||||
const race *rc_clone = rc_find("clone");
|
||||
const item_type *it_potion = it_find("lifepotion");
|
||||
|
||||
if (rc_clone && it_potion) {
|
||||
region *r;
|
||||
for (r = regions; r; r = r->next) {
|
||||
unit * u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (!fval(u, UFL_MARK)) {
|
||||
if (u_race(u) == rc_clone) {
|
||||
attrib *a = a_find(u->attribs, &at_clonemage);
|
||||
unit * um = NULL;
|
||||
fset(u, UFL_MARK);
|
||||
if (a) {
|
||||
um = (unit *)a->data.v;
|
||||
fset(um, UFL_MARK);
|
||||
}
|
||||
}
|
||||
else {
|
||||
attrib *a = a_find(u->attribs, &at_clone);
|
||||
if (a) {
|
||||
unit *uc = (unit *)a->data.v;
|
||||
fset(u, UFL_MARK);
|
||||
fset(uc, UFL_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (r = regions; r; r = r->next) {
|
||||
unit * u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (fval(u, UFL_MARK)) {
|
||||
if (u_race(u) == rc_clone) {
|
||||
fix_clone(u);
|
||||
}
|
||||
else {
|
||||
fix_clone_mage(u, it_potion);
|
||||
}
|
||||
freset(u, UFL_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fix_familiars(void (*callback)(unit *)) {
|
||||
region *r;
|
||||
for (r = regions; r; r = r->next) {
|
||||
|
@ -1586,12 +1652,17 @@ int read_game(gamedata *data)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data->version < FIX_CLONES_VERSION) {
|
||||
fix_clones();
|
||||
}
|
||||
if (data->version < FAMILIAR_FIX_VERSION) {
|
||||
fix_familiars(fix_fam_triggers);
|
||||
}
|
||||
if (data->version < FAMILIAR_FIXSPELLBOOK_VERSION) {
|
||||
fix_familiars(fix_fam_mage);
|
||||
fix_familiars(fix_fam_spells);
|
||||
}
|
||||
if (data->version < FIX_MIGRANT_AURA_VERSION) {
|
||||
fix_familiars(fix_fam_migrant);
|
||||
}
|
||||
|
||||
log_debug("Done loading turn %d.", turn);
|
||||
|
|
|
@ -470,7 +470,7 @@ static void test_shipspeed_stormwind(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
register_shipcurse();
|
||||
assert(sh && cap && crew);
|
||||
|
||||
|
@ -488,7 +488,7 @@ static void test_shipspeed_nodrift(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
register_shipcurse();
|
||||
assert(sh && cap && crew);
|
||||
|
||||
|
@ -503,7 +503,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
register_shipcurse();
|
||||
assert(sh && cap && crew);
|
||||
|
||||
|
@ -519,7 +519,7 @@ static void test_shipspeed_at_speedup(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
assert(sh && cap && crew);
|
||||
|
||||
a = a_new(&at_speedup);
|
||||
|
@ -536,7 +536,7 @@ static void test_shipspeed_race_bonus(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
assert(sh && cap && crew);
|
||||
|
||||
rc = rc_get_or_create(cap->_race->_name);
|
||||
|
@ -551,7 +551,7 @@ static void test_shipspeed_damage(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
assert(sh && cap && crew);
|
||||
|
||||
sh->damage = 1;
|
||||
|
@ -563,6 +563,32 @@ static void test_shipspeed_damage(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_maximum_shipspeed(CuTest *tc) {
|
||||
ship *sh;
|
||||
unit *cap, *crew;
|
||||
race *rc;
|
||||
struct faction *f;
|
||||
attrib *a;
|
||||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
rc = test_create_race("aquarian");
|
||||
rc->flags |= RCF_SHIPSPEED;
|
||||
f = test_create_faction(rc);
|
||||
setup_crew(sh, f, &cap, &crew);
|
||||
CuAssertIntEquals(tc, sh->type->range + 1, shipspeed(sh, cap));
|
||||
create_curse(0, &sh->attribs, &ct_stormwind, 1, 1, 1, 0);
|
||||
CuAssertIntEquals(tc, 2 * sh->type->range + 1, shipspeed(sh, cap));
|
||||
create_curse(0, &sh->attribs, &ct_nodrift, 1, 1, 1, 0);
|
||||
CuAssertIntEquals(tc, 2 * sh->type->range + 2, shipspeed(sh, cap));
|
||||
a = a_new(&at_speedup);
|
||||
a->data.i = 3;
|
||||
a_add(&sh->attribs, a);
|
||||
CuAssertIntEquals(tc, 2 * sh->type->range + 5, shipspeed(sh, cap));
|
||||
create_curse(0, &sh->attribs, &ct_shipspeedup, 1, 1, 4, 0);
|
||||
CuAssertIntEquals(tc, 2 * sh->type->range + 9, shipspeed(sh, cap));
|
||||
}
|
||||
|
||||
static void test_shipspeed(CuTest *tc) {
|
||||
ship *sh;
|
||||
const ship_type *stype;
|
||||
|
@ -574,7 +600,7 @@ static void test_shipspeed(CuTest *tc) {
|
|||
|
||||
CuAssertIntEquals_Msg(tc, "ship without a captain cannot move", 0, shipspeed(sh, NULL));
|
||||
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
|
||||
CuAssertPtrEquals(tc, cap, ship_owner(sh));
|
||||
CuAssertIntEquals_Msg(tc, "ship with fully skilled crew can sail at max speed", 2, shipspeed(sh, cap));
|
||||
|
@ -603,7 +629,7 @@ static void test_shipspeed_max_range(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
sh = setup_ship();
|
||||
setup_crew(sh, 0, &cap, &crew);
|
||||
setup_crew(sh, NULL, &cap, &crew);
|
||||
config_set("movement.shipspeed.skillbonus", "5");
|
||||
r = sh->region;
|
||||
f = test_create_faction(NULL);
|
||||
|
@ -649,5 +675,6 @@ CuSuite *get_ship_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_shipspeed_race_bonus);
|
||||
SUITE_ADD_TEST(suite, test_shipspeed_damage);
|
||||
SUITE_ADD_TEST(suite, test_shipspeed_max_range);
|
||||
SUITE_ADD_TEST(suite, test_maximum_shipspeed);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1812,17 +1812,27 @@ int maintenance_cost(const struct unit *u)
|
|||
return u_race(u)->maintenance * u->number;
|
||||
}
|
||||
|
||||
static skill_t limited_skills[] = { SK_MAGIC, SK_ALCHEMY, SK_TACTICS, SK_SPY, SK_HERBALISM, NOSKILL };
|
||||
static skill_t limited_skills[] = { SK_ALCHEMY, SK_HERBALISM, SK_MAGIC, SK_SPY, SK_TACTICS, NOSKILL };
|
||||
|
||||
bool is_limited_skill(skill_t sk)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; limited_skills[i] != NOSKILL; ++i) {
|
||||
if (sk == limited_skills[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_limited_skills(const struct unit * u)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
for (j = 0; limited_skills[j] != NOSKILL; ++j) {
|
||||
if (sv->id == limited_skills[j]) {
|
||||
return true;
|
||||
}
|
||||
if (is_limited_skill(sv->id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -251,6 +251,7 @@ extern "C" {
|
|||
bool has_horses(const struct unit *u);
|
||||
int maintenance_cost(const struct unit *u);
|
||||
bool has_limited_skills(const struct unit *u);
|
||||
bool is_limited_skill(skill_t sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#ifndef ERESSEA_VERSION
|
||||
/* the version number, if it was not passed to make with -D */
|
||||
#define ERESSEA_VERSION "3.19.0"
|
||||
#define ERESSEA_VERSION "3.20.0"
|
||||
#endif
|
||||
|
||||
const char *eressea_version(void) {
|
||||
|
|
102
src/laws.c
102
src/laws.c
|
@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "battle.h"
|
||||
#include "contact.h"
|
||||
#include "economy.h"
|
||||
#include "give.h"
|
||||
#include "market.h"
|
||||
#include "morale.h"
|
||||
#include "monsters.h"
|
||||
|
@ -395,8 +396,7 @@ static void peasants(region * r, int rule)
|
|||
dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE);
|
||||
|
||||
if (dead > 0) {
|
||||
message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead));
|
||||
msg_release(msg);
|
||||
ADDMSG(&r->msgs, msg_message("phunger", "dead", dead));
|
||||
peasants -= dead;
|
||||
}
|
||||
|
||||
|
@ -941,6 +941,52 @@ int leave_cmd(unit * u, struct order *ord)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void transfer_faction(faction *fsrc, faction *fdst) {
|
||||
unit *u;
|
||||
skill_t sk;
|
||||
int skill_count[MAXSKILLS];
|
||||
int skill_limit[MAXSKILLS];
|
||||
|
||||
for (sk = 0; sk != MAXSKILLS; ++sk) {
|
||||
skill_limit[sk] = faction_skill_limit(fdst, sk);
|
||||
}
|
||||
memset(skill_count, 0, sizeof(skill_count));
|
||||
|
||||
for (u = fdst->units; u != NULL; u = u->nextF) {
|
||||
if (u->skills) {
|
||||
int i;
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
const skill *sv = u->skills + i;
|
||||
skill_t sk = (skill_t)sv->id;
|
||||
skill_count[sk] += u->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u = fsrc->units; u != NULL; u = u->nextF) {
|
||||
if (u_race(u) == fdst->race) {
|
||||
u->flags &= ~UFL_HERO;
|
||||
if (give_unit_allowed(u) == 0) {
|
||||
if (u->skills) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
const skill *sv = u->skills + i;
|
||||
skill_t sk = (skill_t)sv->id;
|
||||
if (skill_count[sk] + u->number > skill_limit[sk]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != u->skill_size) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
u_setfaction(u, fdst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int quit_cmd(unit * u, struct order *ord)
|
||||
{
|
||||
char token[128];
|
||||
|
@ -952,7 +998,37 @@ int quit_cmd(unit * u, struct order *ord)
|
|||
assert(kwd == K_QUIT);
|
||||
passwd = gettoken(token, sizeof(token));
|
||||
if (checkpasswd(f, (const char *)passwd)) {
|
||||
fset(f, FFL_QUIT);
|
||||
int flags = FFL_QUIT;
|
||||
if (rule_transfermen()) {
|
||||
param_t p;
|
||||
p = getparam(f->locale);
|
||||
if (p == P_FACTION) {
|
||||
faction *f2 = getfaction();
|
||||
if (f2 == NULL) {
|
||||
cmistake(u, ord, 66, MSG_EVENT);
|
||||
flags = 0;
|
||||
}
|
||||
else if (f->race != f2->race) {
|
||||
cmistake(u, ord, 281, MSG_EVENT);
|
||||
flags = 0;
|
||||
}
|
||||
else {
|
||||
unit *u2;
|
||||
for (u2 = u->region->units; u2; u2 = u2->next) {
|
||||
if (u2->faction == f2 && ucontact(u2, u)) {
|
||||
transfer_faction(u->faction, u2->faction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (u2 == NULL) {
|
||||
/* no target unit found */
|
||||
cmistake(u, ord, 0, MSG_EVENT);
|
||||
flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
f->flags |= flags;
|
||||
}
|
||||
else {
|
||||
char buffer[64];
|
||||
|
@ -1488,7 +1564,7 @@ int display_cmd(unit * u, struct order *ord)
|
|||
{
|
||||
char token[128];
|
||||
char **s = NULL;
|
||||
const char *str;
|
||||
char *str;
|
||||
region *r = u->region;
|
||||
|
||||
init_order_depr(ord);
|
||||
|
@ -1525,11 +1601,19 @@ int display_cmd(unit * u, struct order *ord)
|
|||
break;
|
||||
|
||||
case P_UNIT:
|
||||
unit_setinfo(u, getstrtoken());
|
||||
str = getstrtoken();
|
||||
if (str) {
|
||||
unicode_utf8_trim(str);
|
||||
}
|
||||
unit_setinfo(u, str);
|
||||
break;
|
||||
|
||||
case P_PRIVAT:
|
||||
usetprivate(u, getstrtoken());
|
||||
str = getstrtoken();
|
||||
if (str) {
|
||||
unicode_utf8_trim(str);
|
||||
}
|
||||
usetprivate(u, str);
|
||||
break;
|
||||
|
||||
case P_REGION:
|
||||
|
@ -1664,7 +1748,7 @@ int name_cmd(struct unit *u, struct order *ord)
|
|||
bool foreign = false;
|
||||
const char *str;
|
||||
|
||||
init_order_depr(ord);
|
||||
init_order(ord, u->faction->locale);
|
||||
str = gettoken(token, sizeof(token));
|
||||
p = findparam_ex(str, u->faction->locale);
|
||||
|
||||
|
@ -2069,7 +2153,7 @@ int banner_cmd(unit * u, struct order *ord)
|
|||
init_order_depr(ord);
|
||||
s = getstrtoken();
|
||||
faction_setbanner(u->faction, s);
|
||||
add_message(&u->faction->msgs, msg_message("changebanner", "value", s));
|
||||
ADDMSG(&u->faction->msgs, msg_message("changebanner", "value", s));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3205,7 +3289,7 @@ static int faction_getmages(faction * f, unit ** results, int numresults)
|
|||
for (u = f->units; u; u = u->nextF) {
|
||||
if (u->number > 0) {
|
||||
struct sc_mage * mage = get_mage(u);
|
||||
if (mage && mage_get_spellbook(mage)) {
|
||||
if (mage) {
|
||||
int level = effskill(u, SK_MAGIC, NULL);
|
||||
if (level > maxlevel) {
|
||||
maxlevel = level;
|
||||
|
|
202
src/laws.test.c
202
src/laws.test.c
|
@ -1,6 +1,7 @@
|
|||
#include <platform.h>
|
||||
#include "laws.h"
|
||||
#include "battle.h"
|
||||
#include "contact.h"
|
||||
#include "guard.h"
|
||||
#include "monsters.h"
|
||||
|
||||
|
@ -221,6 +222,21 @@ static void test_display_cmd(CuTest *tc) {
|
|||
CuAssertStrEquals(tc, "Hodor", unit_getinfo(u));
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_DISPLAY, f->locale, "%s ' Klabautermann '", LOC(f->locale, parameters[P_UNIT]));
|
||||
CuAssertIntEquals(tc, 0, display_cmd(u, ord));
|
||||
CuAssertStrEquals(tc, "Klabautermann", unit_getinfo(u));
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_DISPLAY, f->locale, "%s Hodor", LOC(f->locale, parameters[P_PRIVAT]));
|
||||
CuAssertIntEquals(tc, 0, display_cmd(u, ord));
|
||||
CuAssertStrEquals(tc, "Hodor", uprivate(u));
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_DISPLAY, f->locale, "%s ' Klabautermann '", LOC(f->locale, parameters[P_PRIVAT]));
|
||||
CuAssertIntEquals(tc, 0, display_cmd(u, ord));
|
||||
CuAssertStrEquals(tc, "Klabautermann", uprivate(u));
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_DISPLAY, f->locale, LOC(f->locale, parameters[P_UNIT]));
|
||||
CuAssertIntEquals(tc, 0, display_cmd(u, ord));
|
||||
CuAssertPtrEquals(tc, NULL, (void *)unit_getinfo(u));
|
||||
|
@ -940,6 +956,12 @@ static void test_name_unit(CuTest *tc) {
|
|||
|
||||
u = setup_name_cmd();
|
||||
f = u->faction;
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s ' Klabauterfrau '", LOC(f->locale, parameters[P_UNIT]));
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Klabauterfrau", u->_name);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_UNIT]));
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Hodor", u->_name);
|
||||
|
@ -960,10 +982,15 @@ static void test_name_region(CuTest *tc) {
|
|||
order *ord;
|
||||
|
||||
u = setup_name_cmd();
|
||||
u_set_building(u, test_create_building(u->region, NULL));
|
||||
f = u->faction;
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s ' Hodor Hodor '", LOC(f->locale, parameters[P_REGION]));
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Hodor Hodor", u->region->land->name);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_REGION]));
|
||||
u_set_building(u, test_create_building(u->region, NULL));
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Hodor", u->region->land->name);
|
||||
free_order(ord);
|
||||
|
@ -980,6 +1007,7 @@ static void test_name_region(CuTest *tc) {
|
|||
static void test_name_building(CuTest *tc) {
|
||||
unit *uo, *u, *ux;
|
||||
faction *f;
|
||||
order *ord;
|
||||
|
||||
u = setup_name_cmd();
|
||||
u->building = test_create_building(u->region, NULL);
|
||||
|
@ -989,29 +1017,33 @@ static void test_name_building(CuTest *tc) {
|
|||
ux = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||
u_set_building(ux, u->building);
|
||||
|
||||
u->thisorder = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_BUILDING]));
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s ' Hodor Hodor '", LOC(f->locale, parameters[P_BUILDING]));
|
||||
building_set_owner(uo);
|
||||
name_cmd(u, u->thisorder);
|
||||
name_cmd(u, ord);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error148"));
|
||||
test_clear_messages(f);
|
||||
|
||||
building_set_owner(u);
|
||||
name_cmd(u, u->thisorder);
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Hodor Hodor", u->building->name);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_BUILDING]));
|
||||
name_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, "Hodor", u->building->name);
|
||||
|
||||
building_setname(u->building, "Home");
|
||||
building_set_owner(ux);
|
||||
name_cmd(u, u->thisorder);
|
||||
name_cmd(u, ord);
|
||||
CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error148"));
|
||||
CuAssertStrEquals(tc, "Hodor", u->building->name);
|
||||
|
||||
test_clear_messages(f);
|
||||
free_order(u->thisorder);
|
||||
u->thisorder = create_order(K_NAME, f->locale, LOC(f->locale, parameters[P_BUILDING]));
|
||||
name_cmd(u, u->thisorder);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_NAME, f->locale, LOC(f->locale, parameters[P_BUILDING]));
|
||||
name_cmd(u, ord);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error84"));
|
||||
CuAssertStrEquals(tc, "Hodor", u->building->name);
|
||||
free_order(ord);
|
||||
|
||||
/* TODO: test BTF_NAMECHANGE:
|
||||
btype->flags |= BTF_NAMECHANGE;
|
||||
|
@ -1837,6 +1869,149 @@ static void test_long_order_on_ocean(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_quit(CuTest *tc) {
|
||||
faction *f;
|
||||
unit *u;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, r);
|
||||
u->thisorder = create_order(K_QUIT, f->locale, "password");
|
||||
|
||||
faction_setpassword(f, "passwort");
|
||||
quit_cmd(u, u->thisorder);
|
||||
CuAssertIntEquals(tc, 0, f->flags & FFL_QUIT);
|
||||
|
||||
faction_setpassword(f, "password");
|
||||
quit_cmd(u, u->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f->flags & FFL_QUIT);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gifting units to another faction upon voluntary death (QUIT).
|
||||
*/
|
||||
static void test_quit_transfer(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
unit *u1, *u2;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f1 = test_create_faction(NULL);
|
||||
faction_setpassword(f1, "password");
|
||||
u1 = test_create_unit(f1, r);
|
||||
f2 = test_create_faction(NULL);
|
||||
u2 = test_create_unit(f2, r);
|
||||
contact_unit(u2, u1);
|
||||
u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s",
|
||||
LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no));
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gifting units with limited skills to another faction.
|
||||
*
|
||||
* This is allowed only up to the limit of the target faction.
|
||||
* Units that would break the limit are not transferred.
|
||||
*/
|
||||
static void test_quit_transfer_limited(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
unit *u1, *u2;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f1 = test_create_faction(NULL);
|
||||
faction_setpassword(f1, "password");
|
||||
u1 = test_create_unit(f1, r);
|
||||
f2 = test_create_faction(NULL);
|
||||
u2 = test_create_unit(f2, r);
|
||||
contact_unit(u2, u1);
|
||||
u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s",
|
||||
LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no));
|
||||
|
||||
set_level(u1, SK_MAGIC, 1);
|
||||
set_level(u2, SK_MAGIC, 1);
|
||||
CuAssertIntEquals(tc, true, has_limited_skills(u1));
|
||||
|
||||
config_set_int("rules.maxskills.magic", 1);
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f1, u1->faction);
|
||||
|
||||
f1->flags -= FFL_QUIT;
|
||||
config_set_int("rules.maxskills.magic", 2);
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only units of the same race can be gifted to another faction.
|
||||
*/
|
||||
static void test_quit_transfer_migrants(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
unit *u1, *u2;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f1 = test_create_faction(NULL);
|
||||
faction_setpassword(f1, "password");
|
||||
u1 = test_create_unit(f1, r);
|
||||
f2 = test_create_faction(NULL);
|
||||
u2 = test_create_unit(f2, r);
|
||||
contact_unit(u2, u1);
|
||||
u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s",
|
||||
LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no));
|
||||
|
||||
u_setrace(u1, test_create_race("smurf"));
|
||||
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f1, u1->faction);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* A hero that is gifted to another faction loses their status.
|
||||
*/
|
||||
static void test_quit_transfer_hero(CuTest *tc) {
|
||||
faction *f1, *f2;
|
||||
unit *u1, *u2;
|
||||
region *r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_plain(0, 0);
|
||||
f1 = test_create_faction(NULL);
|
||||
faction_setpassword(f1, "password");
|
||||
u1 = test_create_unit(f1, r);
|
||||
f2 = test_create_faction(NULL);
|
||||
u2 = test_create_unit(f2, r);
|
||||
contact_unit(u2, u1);
|
||||
u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s",
|
||||
LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no));
|
||||
|
||||
u1->flags |= UFL_HERO;
|
||||
|
||||
quit_cmd(u1, u1->thisorder);
|
||||
CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT);
|
||||
CuAssertPtrEquals(tc, f2, u1->faction);
|
||||
CuAssertIntEquals(tc, 0, u1->flags & UFL_HERO);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_laws_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -1912,6 +2087,11 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
||||
SUITE_ADD_TEST(suite, test_long_orders);
|
||||
SUITE_ADD_TEST(suite, test_long_order_on_ocean);
|
||||
SUITE_ADD_TEST(suite, test_quit);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer_limited);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer_migrants);
|
||||
SUITE_ADD_TEST(suite, test_quit_transfer_hero);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
116
src/magic.c
116
src/magic.c
|
@ -117,6 +117,11 @@ typedef struct sc_mage {
|
|||
struct spellbook *spellbook;
|
||||
} sc_mage;
|
||||
|
||||
void mage_set_spellpoints(sc_mage *m, int aura)
|
||||
{
|
||||
m->spellpoints = aura;
|
||||
}
|
||||
|
||||
int mage_get_spellpoints(const sc_mage *m)
|
||||
{
|
||||
return m ? m->spellpoints : 0;
|
||||
|
@ -603,7 +608,7 @@ void set_spellpoints(unit * u, int sp)
|
|||
{
|
||||
sc_mage *m = get_mage(u);
|
||||
if (m) {
|
||||
m->spellpoints = sp;
|
||||
mage_set_spellpoints(m, sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -615,18 +620,6 @@ int change_spellpoints(unit * u, int mp)
|
|||
return mage_change_spellpoints(get_mage(u), mp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bietet die Moeglichkeit, die maximale Anzahl der Magiepunkte mit
|
||||
* Regionszaubern oder Attributen zu beinflussen
|
||||
*/
|
||||
static int get_spchange(const unit * u)
|
||||
{
|
||||
sc_mage *m;
|
||||
|
||||
m = get_mage(u);
|
||||
return m ? m->spchange : 0;
|
||||
}
|
||||
|
||||
/* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte
|
||||
* haben.
|
||||
* Manche Rassen haben einen zusaetzlichen Multiplikator
|
||||
|
@ -655,12 +648,16 @@ int max_spellpoints(const struct unit *u, const region * r)
|
|||
double potenz = 2.1;
|
||||
double divisor = 1.2;
|
||||
const struct resource_type *rtype;
|
||||
const sc_mage *m;
|
||||
|
||||
assert(u);
|
||||
m = get_mage(u);
|
||||
if (!m) return 0;
|
||||
if (!r) r = u->region;
|
||||
|
||||
sk = effskill(u, SK_MAGIC, r);
|
||||
msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1) + get_spchange(u);
|
||||
msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1);
|
||||
msp += m->spchange;
|
||||
|
||||
rtype = rt_find("aurafocus");
|
||||
if (rtype && i_get(u->items, rtype->itype) > 0) {
|
||||
|
@ -1464,44 +1461,47 @@ void regenerate_aura(void)
|
|||
|
||||
for (r = regions; r; r = r->next) {
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (u->number && is_mage(u)) {
|
||||
aura = get_spellpoints(u);
|
||||
auramax = max_spellpoints_depr(r, u);
|
||||
if (aura < auramax) {
|
||||
struct building *b = inside_building(u);
|
||||
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
||||
reg_aura = regeneration(u);
|
||||
if (u->number && u->attribs) {
|
||||
sc_mage *m = get_mage(u);
|
||||
if (m) {
|
||||
aura = mage_get_spellpoints(m);
|
||||
auramax = max_spellpoints(u, r);
|
||||
if (aura < auramax) {
|
||||
struct building *b = inside_building(u);
|
||||
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
|
||||
reg_aura = regeneration(u);
|
||||
|
||||
/* Magierturm erhoeht die Regeneration um 75% */
|
||||
/* Steinkreis erhoeht die Regeneration um 50% */
|
||||
if (btype)
|
||||
reg_aura *= btype->auraregen;
|
||||
/* Magierturm erhoeht die Regeneration um 75% */
|
||||
/* Steinkreis erhoeht die Regeneration um 50% */
|
||||
if (btype)
|
||||
reg_aura *= btype->auraregen;
|
||||
|
||||
/* Bonus/Malus durch Zauber */
|
||||
mod = get_curseeffect(u->attribs, &ct_auraboost);
|
||||
if (mod > 0) {
|
||||
reg_aura = (reg_aura * mod) / 100.0;
|
||||
/* Bonus/Malus durch Zauber */
|
||||
mod = get_curseeffect(u->attribs, &ct_auraboost);
|
||||
if (mod > 0) {
|
||||
reg_aura = (reg_aura * mod) / 100.0;
|
||||
}
|
||||
|
||||
/* Einfluss von Artefakten */
|
||||
/* TODO (noch gibs keine) */
|
||||
|
||||
/* maximal Differenz bis Maximale-Aura regenerieren
|
||||
* mindestens 1 Aura pro Monat */
|
||||
regen = (int)reg_aura;
|
||||
reg_aura -= regen;
|
||||
if (chance(reg_aura)) {
|
||||
++regen;
|
||||
}
|
||||
if (regen < 1) regen = 1;
|
||||
if (regen > auramax - aura) regen = auramax - aura;
|
||||
|
||||
aura += regen;
|
||||
ADDMSG(&u->faction->msgs, msg_message("regenaura",
|
||||
"unit region amount", u, r, regen));
|
||||
}
|
||||
|
||||
/* Einfluss von Artefakten */
|
||||
/* TODO (noch gibs keine) */
|
||||
|
||||
/* maximal Differenz bis Maximale-Aura regenerieren
|
||||
* mindestens 1 Aura pro Monat */
|
||||
regen = (int)reg_aura;
|
||||
reg_aura -= regen;
|
||||
if (chance(reg_aura)) {
|
||||
++regen;
|
||||
}
|
||||
if (regen < 1) regen = 1;
|
||||
if (regen > auramax - aura) regen = auramax - aura;
|
||||
|
||||
aura += regen;
|
||||
ADDMSG(&u->faction->msgs, msg_message("regenaura",
|
||||
"unit region amount", u, r, regen));
|
||||
if (aura > auramax) aura = auramax;
|
||||
mage_set_spellpoints(m, aura);
|
||||
}
|
||||
if (aura > auramax) aura = auramax;
|
||||
set_spellpoints(u, aura);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2251,12 +2251,29 @@ static int copy_spell_cb(spellbook_entry *sbe, void *udata) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Entferne Magie-Attribut von Migranten, die keine Vertrauten sind.
|
||||
*
|
||||
* Einmalige Reparatur von Vertrauten (Bug 2585).
|
||||
*/
|
||||
void fix_fam_migrant(unit *u) {
|
||||
if (!is_familiar(u)) {
|
||||
a_removeall(&u->attribs, &at_mage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Einheiten, die Vertraute sind, bekommen ihre fehlenden Zauber.
|
||||
*
|
||||
* Einmalige Reparatur von Vertrauten (Bugs 2451, 2517).
|
||||
*/
|
||||
void fix_fam_mage(unit *u) {
|
||||
void fix_fam_spells(unit *u) {
|
||||
sc_mage *dmage;
|
||||
unit *du = unit_create(0);
|
||||
|
||||
if (!is_familiar(u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
u_setrace(du, u_race(u));
|
||||
dmage = create_mage(du, M_GRAY);
|
||||
equip_familiar(du);
|
||||
|
@ -2286,7 +2303,6 @@ void fix_fam_mage(unit *u) {
|
|||
|
||||
void create_newfamiliar(unit * mage, unit * fam)
|
||||
{
|
||||
|
||||
create_mage(fam, M_GRAY);
|
||||
set_familiar(mage, fam);
|
||||
equip_familiar(fam);
|
||||
|
|
|
@ -210,6 +210,7 @@ extern "C" {
|
|||
const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level);
|
||||
struct spellbook * mage_get_spellbook(const struct sc_mage * mage);
|
||||
int mage_get_spellpoints(const struct sc_mage *m);
|
||||
void mage_set_spellpoints(struct sc_mage *m, int aura);
|
||||
int mage_change_spellpoints(struct sc_mage *m, int delta);
|
||||
|
||||
enum magic_t unit_get_magic(const struct unit *u);
|
||||
|
@ -259,7 +260,7 @@ extern "C" {
|
|||
/* veraendert die maximalen Magiepunkte einer Einheit */
|
||||
|
||||
/* Zaubern */
|
||||
extern double spellpower(struct region *r, struct unit *u, const struct spell * sp,
|
||||
double spellpower(struct region *r, struct unit *u, const struct spell * sp,
|
||||
int cast_level, struct order *ord);
|
||||
/* ermittelt die Staerke eines Spruchs */
|
||||
bool fumble(struct region *r, struct unit *u, const struct spell * sp,
|
||||
|
@ -315,7 +316,7 @@ extern "C" {
|
|||
int resist_bonus);
|
||||
/* gibt false zurueck, wenn der Zauber gelingt, true, wenn das Ziel
|
||||
* widersteht */
|
||||
extern struct spell * unit_getspell(struct unit *u, const char *s,
|
||||
struct spell * unit_getspell(struct unit *u, const char *s,
|
||||
const struct locale *lang);
|
||||
const char *magic_name(magic_t mtype, const struct locale *lang);
|
||||
|
||||
|
@ -329,7 +330,8 @@ extern "C" {
|
|||
void create_newfamiliar(struct unit *mage, struct unit *familiar);
|
||||
void create_newclone(struct unit *mage, struct unit *familiar);
|
||||
|
||||
void fix_fam_mage(struct unit *u);
|
||||
void fix_fam_spells(struct unit *u);
|
||||
void fix_fam_migrant(struct unit *u);
|
||||
|
||||
const char *spell_info(const struct spell *sp,
|
||||
const struct locale *lang);
|
||||
|
|
192
src/magic.test.c
192
src/magic.test.c
|
@ -108,7 +108,7 @@ void test_pay_spell(CuTest * tc)
|
|||
|
||||
test_setup();
|
||||
init_resources();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, r);
|
||||
CuAssertPtrNotNull(tc, u);
|
||||
|
@ -142,7 +142,7 @@ void test_pay_spell_failure(CuTest * tc)
|
|||
|
||||
test_setup();
|
||||
init_resources();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, r);
|
||||
CuAssertPtrNotNull(tc, u);
|
||||
|
@ -179,7 +179,7 @@ void test_getspell_unit(CuTest * tc)
|
|||
struct locale * lang;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, r);
|
||||
create_mage(u, M_GWYRRD);
|
||||
|
@ -207,7 +207,7 @@ void test_getspell_faction(CuTest * tc)
|
|||
struct locale * lang;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -238,7 +238,7 @@ void test_getspell_school(CuTest * tc)
|
|||
struct spellbook * book;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -268,7 +268,7 @@ void test_set_pre_combatspell(CuTest * tc)
|
|||
const int index = 0;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -300,7 +300,7 @@ void test_set_main_combatspell(CuTest * tc)
|
|||
const int index = 1;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -332,7 +332,7 @@ void test_set_post_combatspell(CuTest * tc)
|
|||
const int index = 2;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -363,7 +363,7 @@ void test_hasspell(CuTest * tc)
|
|||
struct region * r;
|
||||
|
||||
test_setup();
|
||||
r = test_create_region(0, 0, NULL);
|
||||
r = test_create_plain(0, 0);
|
||||
f = test_create_faction(NULL);
|
||||
f->magiegebiet = M_TYBIED;
|
||||
u = test_create_unit(f, r);
|
||||
|
@ -405,7 +405,7 @@ void test_multi_cast(CuTest *tc) {
|
|||
locale_setstring(lang, mkname("spell", sp->sname), "Feuerball");
|
||||
CuAssertStrEquals(tc, "Feuerball", spell_name(sp, lang));
|
||||
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
set_level(u, SK_MAGIC, 10);
|
||||
unit_add_spell(u, sp, 1);
|
||||
CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang));
|
||||
|
@ -426,7 +426,7 @@ static void test_magic_resistance(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
rc = test_create_race("human");
|
||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL));
|
||||
u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0));
|
||||
CuAssertTrue(tc, frac_equal(rc->magres, magic_resistance(u)));
|
||||
rc->magres = frac_one;
|
||||
CuAssert(tc, "magic resistance is capped at 0.9", frac_equal(magic_resistance(u), frac_make(9, 10)));
|
||||
|
@ -442,23 +442,153 @@ static void test_magic_resistance(CuTest *tc) {
|
|||
static void test_max_spellpoints(CuTest *tc) {
|
||||
unit *u;
|
||||
race *rc;
|
||||
item_type *it_aura;
|
||||
|
||||
test_setup();
|
||||
rc = test_create_race("human");
|
||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL));
|
||||
CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u));
|
||||
rc->maxaura = 100;
|
||||
CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u));
|
||||
rc->maxaura = 200;
|
||||
CuAssertIntEquals(tc, 2, max_spellpoints_depr(u->region, u));
|
||||
u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0));
|
||||
CuAssertIntEquals(tc, 0, max_spellpoints_depr(u->region, u));
|
||||
CuAssertIntEquals(tc, 0, max_spellpoints(u, u->region));
|
||||
CuAssertIntEquals(tc, 0, max_spellpoints(u, NULL));
|
||||
create_mage(u, M_GWYRRD);
|
||||
rc->maxaura = 100;
|
||||
CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL));
|
||||
rc->maxaura = 200;
|
||||
CuAssertIntEquals(tc, 2, max_spellpoints(u, NULL));
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertIntEquals(tc, 3, max_spellpoints_depr(u->region, u));
|
||||
CuAssertIntEquals(tc, 3, max_spellpoints(u, NULL));
|
||||
set_level(u, SK_MAGIC, 2);
|
||||
CuAssertIntEquals(tc, 9, max_spellpoints_depr(u->region, u));
|
||||
CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL));
|
||||
/* permanent aura loss: */
|
||||
CuAssertIntEquals(tc, 7, change_maxspellpoints(u, -2));
|
||||
CuAssertIntEquals(tc, 7, max_spellpoints_depr(u->region, u));
|
||||
CuAssertIntEquals(tc, 7, max_spellpoints(u, NULL));
|
||||
/* aurafocus: */
|
||||
it_aura = test_create_itemtype("aurafocus");
|
||||
i_change(&u->items, it_aura, 1);
|
||||
CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_regenerate_aura(CuTest *tc) {
|
||||
unit *u;
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
create_mage(u, M_GWYRRD);
|
||||
CuAssertIntEquals(tc, 0, get_spellpoints(u));
|
||||
CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL));
|
||||
regenerate_aura();
|
||||
CuAssertIntEquals(tc, 1, get_spellpoints(u));
|
||||
|
||||
u = test_create_unit(u->faction, u->region);
|
||||
create_mage(u, M_GRAY);
|
||||
CuAssertIntEquals(tc, 0, get_spellpoints(u));
|
||||
CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL));
|
||||
regenerate_aura();
|
||||
CuAssertIntEquals(tc, 1, get_spellpoints(u));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Bug 2582.
|
||||
*
|
||||
* Migrant units that are not familiars, but whose race has a maxaura
|
||||
* must not regenerate aura.
|
||||
*/
|
||||
static void test_regenerate_aura_migrants(CuTest *tc) {
|
||||
unit *u;
|
||||
race *rc;
|
||||
|
||||
test_setup();
|
||||
rc = test_create_race("demon");
|
||||
rc->maxaura = 100;
|
||||
rc->flags |= RCF_FAMILIAR;
|
||||
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u_setrace(u, rc);
|
||||
CuAssertIntEquals(tc, 0, get_spellpoints(u));
|
||||
regenerate_aura();
|
||||
CuAssertIntEquals(tc, 0, get_spellpoints(u));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_fix_fam_migrants(CuTest *tc) {
|
||||
unit *u, *mage;
|
||||
race *rc;
|
||||
|
||||
test_setup();
|
||||
rc = test_create_race("demon");
|
||||
rc->maxaura = 100;
|
||||
rc->flags |= RCF_FAMILIAR;
|
||||
|
||||
/* u is a migrant with at_mage attribute, but not a familiar */
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u_setrace(u, rc);
|
||||
create_mage(u, M_GRAY);
|
||||
CuAssertTrue(tc, !is_familiar(u));
|
||||
CuAssertPtrNotNull(tc, get_mage(u));
|
||||
fix_fam_migrant(u);
|
||||
CuAssertTrue(tc, !is_familiar(u));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
|
||||
/* u is a familiar, and stays unchanged: */
|
||||
mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u_setrace(u, rc);
|
||||
/* reproduce the bug, create a broken familiar: */
|
||||
create_newfamiliar(mage, u);
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertTrue(tc, is_familiar(u));
|
||||
CuAssertPtrNotNull(tc, get_mage(u));
|
||||
fix_fam_migrant(u);
|
||||
CuAssertTrue(tc, is_familiar(u));
|
||||
CuAssertPtrNotNull(tc, get_mage(u));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static bool equip_spell(unit *u, const char *eqname, int mask) {
|
||||
spell * sp = find_spell("test");
|
||||
unit_add_spell(u, sp, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void test_fix_fam_spells(CuTest *tc) {
|
||||
unit *u, *mage;
|
||||
race *rc;
|
||||
spell * sp;
|
||||
|
||||
test_setup();
|
||||
sp = create_spell("test");
|
||||
rc = test_create_race("demon");
|
||||
rc->maxaura = 100;
|
||||
rc->flags |= RCF_FAMILIAR;
|
||||
|
||||
/* u is a familiar, and gets equipped: */
|
||||
mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u_setrace(u, rc);
|
||||
/* reproduce the bug, create a broken familiar: */
|
||||
callbacks.equip_unit = NULL;
|
||||
create_newfamiliar(mage, u);
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u));
|
||||
CuAssertTrue(tc, !u_hasspell(u, sp));
|
||||
callbacks.equip_unit = equip_spell;
|
||||
CuAssertTrue(tc, is_familiar(u));
|
||||
fix_fam_spells(u);
|
||||
CuAssertTrue(tc, is_familiar(u));
|
||||
CuAssertPtrNotNull(tc, unit_get_spellbook(u));
|
||||
CuAssertTrue(tc, u_hasspell(u, sp));
|
||||
|
||||
/* u is a migrant, and does not get equipped: */
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u_setrace(u, rc);
|
||||
CuAssertTrue(tc, !is_familiar(u));
|
||||
fix_fam_spells(u);
|
||||
CuAssertTrue(tc, !is_familiar(u));
|
||||
CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
|
@ -470,7 +600,7 @@ static void test_illusioncastle(CuTest *tc)
|
|||
test_setup();
|
||||
btype = test_create_buildingtype("castle");
|
||||
bt_icastle = test_create_buildingtype("illusioncastle");
|
||||
b = test_create_building(test_create_region(0, 0, NULL), bt_icastle);
|
||||
b = test_create_building(test_create_plain(0, 0), bt_icastle);
|
||||
b->size = 1;
|
||||
make_icastle(b, btype, 10);
|
||||
a = a_find(b->attribs, &at_icastle);
|
||||
|
@ -488,7 +618,7 @@ static void test_is_mage(CuTest *tc) {
|
|||
struct sc_mage *mage;
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
CuAssertTrue(tc, !is_mage(u));
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
|
@ -505,7 +635,7 @@ static void test_get_mage(CuTest *tc) {
|
|||
struct sc_mage *mage;
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR));
|
||||
CuAssertPtrEquals(tc, mage, get_mage(u));
|
||||
|
@ -517,8 +647,8 @@ static void test_familiar_set(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL));
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
fam = test_create_unit(mag->faction, test_create_plain(0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar_mage(fam));
|
||||
CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod));
|
||||
|
@ -537,8 +667,8 @@ static void test_familiar_age(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL));
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
fam = test_create_unit(mag->faction, test_create_plain(0, 0));
|
||||
set_familiar(mag, fam);
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
|
@ -568,8 +698,8 @@ static void test_familiar_equip(CuTest *tc) {
|
|||
|
||||
test_setup();
|
||||
callbacks.equip_unit = equip_callback;
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u = test_create_unit(mag->faction, test_create_region(0, 0, NULL));
|
||||
mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
u = test_create_unit(mag->faction, test_create_plain(0, 0));
|
||||
CuAssertStrEquals(tc, "human", u->_race->_name);
|
||||
set_familiar(mag, u);
|
||||
create_newfamiliar(mag, u);
|
||||
|
@ -612,5 +742,9 @@ CuSuite *get_magic_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_magic_resistance);
|
||||
SUITE_ADD_TEST(suite, test_max_spellpoints);
|
||||
SUITE_ADD_TEST(suite, test_illusioncastle);
|
||||
SUITE_ADD_TEST(suite, test_regenerate_aura);
|
||||
SUITE_ADD_TEST(suite, test_regenerate_aura_migrants);
|
||||
SUITE_ADD_TEST(suite, test_fix_fam_spells);
|
||||
SUITE_ADD_TEST(suite, test_fix_fam_migrants);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
const terrain_type *random_terrain(const terrain_type * terrains[],
|
||||
static const terrain_type *random_terrain_select(const terrain_type * terrains[],
|
||||
int distribution[], int size)
|
||||
{
|
||||
int ndistribution = size;
|
||||
|
@ -583,7 +583,7 @@ int autoseed(newfaction ** players, int nsize, int max_agediff)
|
|||
break;
|
||||
}
|
||||
else {
|
||||
terraform_region(r, random_terrain(terrainarr, distribution, nterrains));
|
||||
terraform_region(r, random_terrain_select(terrainarr, distribution, nterrains));
|
||||
--isize;
|
||||
}
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ int autoseed(newfaction ** players, int nsize, int max_agediff)
|
|||
pnormalize(&x, &y, pl);
|
||||
rn = new_region(x, y, pl, 0);
|
||||
if (rng_int() % SPECIALCHANCE < special) {
|
||||
terrain = random_terrain(terrainarr, distribution, nterrains);
|
||||
terrain = random_terrain_select(terrainarr, distribution, nterrains);
|
||||
special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */
|
||||
}
|
||||
else {
|
||||
|
@ -698,23 +698,21 @@ region *regionqueue_pop(region_list ** rlist)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define GEOMAX 8
|
||||
#define GEOMAX 7
|
||||
static struct geo {
|
||||
int distribution;
|
||||
terrain_t type;
|
||||
} geography_e3[GEOMAX] = {
|
||||
{
|
||||
8, T_OCEAN }, {
|
||||
3, T_SWAMP }, {
|
||||
1, T_VOLCANO }, {
|
||||
3, T_DESERT }, {
|
||||
4, T_HIGHLAND }, {
|
||||
3, T_MOUNTAIN }, {
|
||||
2, T_GLACIER }, {
|
||||
1, T_PLAIN }
|
||||
{ 8, T_OCEAN },
|
||||
{ 3, T_SWAMP },
|
||||
{ 3, T_DESERT },
|
||||
{ 4, T_HIGHLAND },
|
||||
{ 3, T_MOUNTAIN },
|
||||
{ 2, T_GLACIER },
|
||||
{ 1, T_PLAIN }
|
||||
};
|
||||
|
||||
const terrain_type *random_terrain_e3(direction_t dir)
|
||||
const terrain_type *random_terrain(direction_t dir)
|
||||
{
|
||||
static const terrain_type **terrainarr = 0;
|
||||
static int *distribution = 0;
|
||||
|
@ -731,7 +729,7 @@ const terrain_type *random_terrain_e3(direction_t dir)
|
|||
distribution[n] = geography_e3[n].distribution;
|
||||
}
|
||||
}
|
||||
return random_terrain(terrainarr, distribution, GEOMAX);
|
||||
return random_terrain_select(terrainarr, distribution, GEOMAX);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -864,8 +862,8 @@ static void starting_region(newfaction ** players, region * r, region * rn[])
|
|||
}
|
||||
}
|
||||
|
||||
/* E3A island generation */
|
||||
int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfactions)
|
||||
/* island generator */
|
||||
int build_island(int x, int y, int minsize, newfaction ** players, int numfactions)
|
||||
{
|
||||
#define MIN_QUALITY 1000
|
||||
int nfactions = 0;
|
||||
|
@ -881,14 +879,14 @@ int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfac
|
|||
r = new_region(x, y, pl, 0);
|
||||
}
|
||||
do {
|
||||
terraform_region(r, random_terrain_e3(NODIRECTION));
|
||||
terraform_region(r, random_terrain(NODIRECTION));
|
||||
} while (!r->land);
|
||||
|
||||
while (r) {
|
||||
fset(r, RF_MARK);
|
||||
if (r->land) {
|
||||
if (nsize < minsize) {
|
||||
nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize - nsize);
|
||||
nsize += random_neighbours(r, &rlist, &random_terrain, minsize - nsize);
|
||||
}
|
||||
else {
|
||||
nsize += random_neighbours(r, &rlist, &get_ocean, minsize - nsize);
|
||||
|
|
|
@ -33,10 +33,8 @@ extern "C" {
|
|||
|
||||
extern int autoseed(newfaction ** players, int nsize, int max_agediff);
|
||||
extern newfaction *read_newfactions(const char *filename);
|
||||
extern const struct terrain_type *random_terrain(const struct terrain_type
|
||||
*terrains[], int distribution[], int size);
|
||||
|
||||
extern int build_island_e3(int x, int y, int minsize, newfaction **players, int numfactions);
|
||||
extern int build_island(int x, int y, int minsize, newfaction **players, int numfactions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -442,7 +442,7 @@ static order *monster_move(region * r, unit * u)
|
|||
if (fval(u_race(u), RCF_DRAGON)) {
|
||||
d = richest_neighbour(r, u->faction, 1);
|
||||
}
|
||||
else if (get_race(RC_TREEMAN)==u_race(u)) {
|
||||
else if (get_race(RC_TREEMAN) == u_race(u)) {
|
||||
d = treeman_neighbour(r);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -32,9 +32,9 @@ static int age_chance(int a, int b, int p) {
|
|||
|
||||
static void evolve_dragon(unit * u, const struct race *rc) {
|
||||
scale_number(u, 1);
|
||||
u->hp = unit_max_hp(u);
|
||||
u_setrace(u, rc);
|
||||
u->irace = NULL;
|
||||
u->hp = unit_max_hp(u);
|
||||
}
|
||||
|
||||
void age_firedragon(unit * u)
|
||||
|
|
|
@ -239,6 +239,7 @@ static void move_iceberg(region * r)
|
|||
"region dir", r, dir));
|
||||
}
|
||||
|
||||
stats_count("iceberg.drift", 1);
|
||||
x = r->x;
|
||||
y = r->y;
|
||||
|
||||
|
@ -379,6 +380,7 @@ static void create_icebergs(void)
|
|||
continue;
|
||||
|
||||
r->terrain = t_iceberg;
|
||||
stats_count("iceberg.terraform", 1);
|
||||
|
||||
fset(r, RF_SELECT);
|
||||
move_iceberg(r);
|
||||
|
@ -603,8 +605,7 @@ void plagues(region * r)
|
|||
}
|
||||
|
||||
if (dead > 0) {
|
||||
message *msg = add_message(&r->msgs, msg_message("pest", "dead", dead));
|
||||
msg_release(msg);
|
||||
ADDMSG(&r->msgs, msg_message("pest", "dead", dead));
|
||||
deathcounts(r, dead);
|
||||
rsetpeasants(r, peasants - dead);
|
||||
}
|
||||
|
|
55
src/report.c
55
src/report.c
|
@ -1216,14 +1216,14 @@ static void statistics(struct stream *out, const region * r, const faction * f)
|
|||
|
||||
if (!markets_module()) {
|
||||
if (buildingtype_exists(r, bt_find("caravan"), true)) {
|
||||
m = msg_message("nr_stat_luxuries", "max", (p * 2) / TRADE_FRACTION);
|
||||
p *= 2;
|
||||
}
|
||||
else {
|
||||
if (p >= TRADE_FRACTION) {
|
||||
m = msg_message("nr_stat_luxuries", "max", p / TRADE_FRACTION);
|
||||
nr_render(m, f->locale, buf, sizeof(buf), f);
|
||||
paragraph(out, buf, 2, 2, 0);
|
||||
msg_release(m);
|
||||
}
|
||||
nr_render(m, f->locale, buf, sizeof(buf), f);
|
||||
paragraph(out, buf, 2, 2, 0);
|
||||
msg_release(m);
|
||||
}
|
||||
|
||||
/* count */
|
||||
|
@ -1545,7 +1545,7 @@ static int show_allies_cb(struct allies *all, faction *af, int status, void *uda
|
|||
}
|
||||
}
|
||||
if (show->num_allies == show->num_listed) {
|
||||
sbs_strcat(sbp, ").");
|
||||
sbs_strcat(sbp, ").\n");
|
||||
pump_paragraph(sbp, show->out, show->maxlen, true);
|
||||
}
|
||||
else {
|
||||
|
@ -1577,11 +1577,24 @@ void report_allies(struct stream *out, size_t maxlen, const struct faction * f,
|
|||
}
|
||||
}
|
||||
|
||||
static void rpline(struct stream *out)
|
||||
{
|
||||
static char line[REPORTWIDTH + 1];
|
||||
if (line[0] != '-') {
|
||||
memset(line, '-', sizeof(line));
|
||||
line[REPORTWIDTH] = '\n';
|
||||
}
|
||||
swrite(line, sizeof(line), 1, out);
|
||||
}
|
||||
|
||||
static void allies(struct stream *out, const faction * f)
|
||||
{
|
||||
const group *g = f->groups;
|
||||
char prefix[64];
|
||||
|
||||
centre(out, LOC(f->locale, "nr_alliances"), false);
|
||||
newline(out);
|
||||
|
||||
if (f->allies) {
|
||||
snprintf(prefix, sizeof(prefix), "%s ", LOC(f->locale, "faction_help"));
|
||||
report_allies(out, REPORTWIDTH, f, f->allies, prefix);
|
||||
|
@ -1660,16 +1673,6 @@ static void guards(struct stream *out, const region * r, const faction * see)
|
|||
}
|
||||
}
|
||||
|
||||
static void rpline(struct stream *out)
|
||||
{
|
||||
static char line[REPORTWIDTH + 1];
|
||||
if (line[0] != '-') {
|
||||
memset(line, '-', sizeof(line));
|
||||
line[REPORTWIDTH] = '\n';
|
||||
}
|
||||
swrite(line, sizeof(line), 1, out);
|
||||
}
|
||||
|
||||
static void list_address(struct stream *out, const faction * uf, selist * seenfactions)
|
||||
{
|
||||
int qi = 0;
|
||||
|
@ -1699,8 +1702,6 @@ static void list_address(struct stream *out, const faction * uf, selist * seenfa
|
|||
}
|
||||
selist_advance(&flist, &qi, 1);
|
||||
}
|
||||
newline(out);
|
||||
rpline(out);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2114,14 +2115,6 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
}
|
||||
}
|
||||
newline(out);
|
||||
ERRNO_CHECK();
|
||||
centre(out, LOC(f->locale, "nr_alliances"), false);
|
||||
newline(out);
|
||||
|
||||
allies(out, f);
|
||||
|
||||
rpline(out);
|
||||
|
||||
ERRNO_CHECK();
|
||||
anyunits = 0;
|
||||
|
||||
|
@ -2134,9 +2127,10 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
continue;
|
||||
/* Beschreibung */
|
||||
|
||||
rpline(out);
|
||||
newline(out);
|
||||
if (r->seen.mode >= seen_unit) {
|
||||
anyunits = 1;
|
||||
newline(out);
|
||||
report_region(out, r, f);
|
||||
if (markets_module() && r->land) {
|
||||
const item_type *lux = r_luxury(r);
|
||||
|
@ -2173,20 +2167,21 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
newline(out);
|
||||
report_travelthru(out, r, f);
|
||||
}
|
||||
newline(out);
|
||||
|
||||
if (wants_stats && r->seen.mode >= seen_travel) {
|
||||
if (r->land || r->seen.mode >= seen_unit) {
|
||||
statistics(out, r, f);
|
||||
newline(out);
|
||||
statistics(out, r, f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Nachrichten an REGION in der Region */
|
||||
if (r->seen.mode >= seen_travel) {
|
||||
message_list *mlist = r_getmessages(r, f);
|
||||
newline(out);
|
||||
if (mlist) {
|
||||
struct mlist **split = merge_messages(mlist, r->msgs);
|
||||
newline(out);
|
||||
rp_messages(out, mlist, f, 0, false);
|
||||
split_messages(mlist, split);
|
||||
}
|
||||
|
@ -2240,7 +2235,6 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
assert(!u);
|
||||
|
||||
newline(out);
|
||||
rpline(out);
|
||||
ERRNO_CHECK();
|
||||
}
|
||||
if (!is_monsters(f)) {
|
||||
|
@ -2249,6 +2243,7 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
paragraph(out, LOC(f->locale, "nr_youaredead"), 0, 2, 0);
|
||||
}
|
||||
else {
|
||||
allies(out, f);
|
||||
list_address(out, f, ctx->addresses);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ static void test_report_allies(CuTest *tc) {
|
|||
f1 = test_create_faction(NULL);
|
||||
f2 = test_create_faction(NULL);
|
||||
f3 = test_create_faction(NULL);
|
||||
snprintf(exp, sizeof(exp), "Wir helfen %s (%s).\n",
|
||||
snprintf(exp, sizeof(exp), "Wir helfen %s (%s).\n\n",
|
||||
factionname(f1),
|
||||
LOC(lang, parameters[P_GUARD]));
|
||||
ally_set(&f->allies, f1, HELP_GUARD);
|
||||
|
@ -211,7 +211,7 @@ static void test_report_allies(CuTest *tc) {
|
|||
factionname(f2),
|
||||
LOC(lang, parameters[P_GIVE]));
|
||||
linebreak = strlen(exp);
|
||||
snprintf(exp, sizeof(exp), "Wir helfen %s (%s), %s (%s)\nund %s (%s).\n",
|
||||
snprintf(exp, sizeof(exp), "Wir helfen %s (%s), %s (%s)\nund %s (%s).\n\n",
|
||||
factionname(f1),
|
||||
LOC(lang, parameters[P_GUARD]),
|
||||
factionname(f2),
|
||||
|
|
|
@ -144,8 +144,6 @@ bool omniscient(const faction *f)
|
|||
return (f->race == rc_template);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *groupid(const struct group *g, const struct faction *f)
|
||||
{
|
||||
typedef char name[OBJECTIDSIZE + 1];
|
||||
|
|
|
@ -2242,13 +2242,12 @@ static int sp_stormwinds(castorder * co)
|
|||
|
||||
sh = pa->param[n]->data.sh;
|
||||
|
||||
/* mit C_SHIP_NODRIFT haben wir kein Problem */
|
||||
if (is_cursed(sh->attribs, &ct_flyingship)) {
|
||||
ADDMSG(&caster->faction->msgs, msg_feedback(caster, co->order,
|
||||
"error_spell_on_flying_ship", "ship", sh))
|
||||
continue;
|
||||
}
|
||||
if (is_cursed(sh->attribs, &ct_shipspeedup)) {
|
||||
if (is_cursed(sh->attribs, &ct_stormwind)) {
|
||||
ADDMSG(&caster->faction->msgs, msg_feedback(caster, co->order,
|
||||
"error_spell_on_ship_already", "ship", sh))
|
||||
continue;
|
||||
|
@ -3110,8 +3109,8 @@ static int sp_chaossuction(castorder * co)
|
|||
create_special_direction(rt, r, 2, "vortex_desc", "vortex", false);
|
||||
new_border(&bt_chaosgate, r, rt);
|
||||
|
||||
add_message(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster));
|
||||
add_message(&rt->msgs, msg_message("chaosgate_effect_2", ""));
|
||||
ADDMSG(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster));
|
||||
ADDMSG(&rt->msgs, msg_message("chaosgate_effect_2", ""));
|
||||
return cast_level;
|
||||
}
|
||||
|
||||
|
@ -3451,7 +3450,7 @@ static bool can_charm(const unit * u, int maxlevel)
|
|||
while (l < h) {
|
||||
int m = (l + h) / 2;
|
||||
if (sk == expskills[m]) {
|
||||
if (skill_limit(u->faction, sk) != INT_MAX) {
|
||||
if (faction_skill_limit(u->faction, sk) != INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
else if ((int)sv->level > maxlevel) {
|
||||
|
|
|
@ -62,7 +62,7 @@ static const char *spell_damage(int sp)
|
|||
{
|
||||
switch (sp) {
|
||||
case 0:
|
||||
/* meist toetlich 20-65 HP */
|
||||
/* meist toedlich 20-65 HP */
|
||||
return "5d10+15";
|
||||
case 1:
|
||||
/* sehr variabel 4-48 HP */
|
||||
|
@ -71,7 +71,7 @@ static const char *spell_damage(int sp)
|
|||
/* leicht verwundet 4-18 HP */
|
||||
return "2d8+2";
|
||||
case 3:
|
||||
/* fast immer toetlich 30-50 HP */
|
||||
/* fast immer toedlich 30-50 HP */
|
||||
return "5d5+25";
|
||||
case 4:
|
||||
/* verwundet 11-26 HP */
|
||||
|
|
|
@ -635,9 +635,9 @@ int study_cmd(unit * u, order * ord)
|
|||
mtype = M_GRAY;
|
||||
}
|
||||
else if (!has_skill(u, SK_MAGIC)) {
|
||||
int mmax = skill_limit(u->faction, SK_MAGIC);
|
||||
int mmax = faction_skill_limit(u->faction, SK_MAGIC);
|
||||
/* Die Einheit ist noch kein Magier */
|
||||
if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
|
||||
if (faction_count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians",
|
||||
"amount", mmax));
|
||||
return -1;
|
||||
|
@ -694,8 +694,8 @@ int study_cmd(unit * u, order * ord)
|
|||
if (sk == SK_ALCHEMY) {
|
||||
maxalchemy = effskill(u, SK_ALCHEMY, NULL);
|
||||
if (!has_skill(u, SK_ALCHEMY)) {
|
||||
int amax = skill_limit(u->faction, SK_ALCHEMY);
|
||||
if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
||||
int amax = faction_skill_limit(u->faction, SK_ALCHEMY);
|
||||
if (faction_count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists",
|
||||
"amount", amax));
|
||||
return -1;
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
#include "vortex.h"
|
||||
|
||||
#include "kernel/calendar.h"
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/alliance.h>
|
||||
#include "kernel/callbacks.h"
|
||||
#include "kernel/config.h"
|
||||
#include "kernel/alliance.h"
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/messages.h>
|
||||
#include <kernel/plane.h>
|
||||
|
@ -228,7 +229,7 @@ static void test_reset(void) {
|
|||
errno = 0;
|
||||
log_error("errno: %d (%s)", error, strerror(error));
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
free_gamedata();
|
||||
free_terrains();
|
||||
free_resources();
|
||||
|
|
|
@ -233,12 +233,12 @@ const char *parse_token_depr(const char **str)
|
|||
return parse_token(str, pbuf, MAXTOKENSIZE);
|
||||
}
|
||||
|
||||
const char *getstrtoken(void)
|
||||
char *getstrtoken(void)
|
||||
{
|
||||
return parse_token((const char **)&states->current_token, pbuf, MAXTOKENSIZE);
|
||||
}
|
||||
|
||||
const char *gettoken(char *lbuf, size_t bufsize)
|
||||
char *gettoken(char *lbuf, size_t bufsize)
|
||||
{
|
||||
return parse_token((const char **)&states->current_token, lbuf, bufsize);
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ extern "C" {
|
|||
void parser_pushstate(void);
|
||||
void parser_popstate(void);
|
||||
bool parser_end(void);
|
||||
const char *getstrtoken(void);
|
||||
const char *gettoken(char *lbuf, size_t bufsize);
|
||||
char *getstrtoken(void);
|
||||
char *gettoken(char *lbuf, size_t bufsize);
|
||||
int getuint(void);
|
||||
int getint(void);
|
||||
int getid(void);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <platform.h>
|
||||
#include "unicode.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
|
@ -36,6 +37,7 @@ int unicode_utf8_trim(utf8_t *buf)
|
|||
{
|
||||
int result = 0, ts = 0;
|
||||
utf8_t *op = buf, *ip = buf, *lc = buf;
|
||||
assert(buf);
|
||||
while (*ip) {
|
||||
size_t size = 1;
|
||||
wint_t wc = *ip;
|
||||
|
|
|
@ -7,9 +7,9 @@ IF EXIST ..\build-vs15 SET BUILD=..\build-vs15\eressea\Debug
|
|||
|
||||
SET SERVER=%BUILD%\eressea.exe
|
||||
%BUILD%\test_eressea.exe
|
||||
%SERVER% ..\scripts\run-tests.lua
|
||||
%SERVER% -re2 ..\scripts\run-tests-e2.lua
|
||||
%SERVER% -re3 ..\scripts\run-tests-e3.lua
|
||||
%SERVER% -v1 ..\scripts\run-tests.lua
|
||||
%SERVER% -v1 -re2 ..\scripts\run-tests-e2.lua
|
||||
%SERVER% -v1 -re3 ..\scripts\run-tests-e3.lua
|
||||
%SERVER% --version
|
||||
PAUSE
|
||||
RMDIR /s /q reports
|
||||
|
|
|
@ -12,5 +12,8 @@ IF exist build-vs%VSVERSION% goto HAVEDIR
|
|||
mkdir build-vs%VSVERSION%
|
||||
:HAVEDIR
|
||||
cd build-vs%VSVERSION%
|
||||
IF NOT EXIST CMakeCache.txt GOTO NOCACHE
|
||||
DEL CMakeCache.txt
|
||||
:NOCACHE
|
||||
"%CMAKE_ROOT%\bin\cmake.exe" -G "Visual Studio %VSVERSION%" -DCMAKE_PREFIX_PATH="%LUA_DEV%;%WIN32_DEV%" -DCMAKE_MODULE_PATH="%SRCDIR%/cmake/Modules" -DCMAKE_SUPPRESS_REGENERATION=TRUE ..
|
||||
PAUSE
|
||||
|
|
Loading…
Reference in New Issue