forked from github/server
Compare commits
No commits in common. "develop" and "2758-smurf" have entirely different histories.
develop
...
2758-smurf
64 changed files with 507 additions and 935 deletions
37
.github/workflows/main.yml
vendored
37
.github/workflows/main.yml
vendored
|
@ -1,37 +0,0 @@
|
|||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CI
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
branches: [ master, develop ]
|
||||
pull_request:
|
||||
branches: [ master, develop ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt install libexpat1-dev libtolua-dev libncurses5-dev libsqlite3-dev libiniparser-dev libcjson-dev libbsd-dev cppcheck shellcheck luarocks clang-tools
|
||||
- name: Run .travis.yml build script
|
||||
uses: ktomk/run-travis-yml@v1
|
||||
with:
|
||||
file: .travis.yml
|
||||
steps: |
|
||||
install
|
||||
script
|
||||
allow-failure: false
|
|
@ -21,4 +21,3 @@ addons:
|
|||
- luarocks
|
||||
os:
|
||||
- linux
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ Here's how you clone and build the source on Linux or macOS:
|
|||
git clone --recursive git://github.com/eressea/server.git source
|
||||
cd source
|
||||
git submodule update --init
|
||||
s/cmake-init
|
||||
s/build
|
||||
|
||||
If you got this far and all went well, you have built the server, and
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"keywords": {
|
||||
"en" : {
|
||||
"plant": "PLANT",
|
||||
"grow": [ "GROW", "BREED" ],
|
||||
"promote": ["PROMOTE", "PROMOTION" ],
|
||||
"locale": ["LANGUAGE", "LOCALE"],
|
||||
"combat": [ "COMBAT", "FIGHT" ]
|
||||
"plant": "PLANT",
|
||||
"grow": [ "GROW", "BREED" ],
|
||||
"promote": ["PROMOTE", "PROMOTION" ],
|
||||
"locale": ["LANGUAGE", "LOCALE"],
|
||||
"combat": [ "COMBAT", "FIGHT" ]
|
||||
},
|
||||
"de": {
|
||||
"//" : "//",
|
||||
|
@ -36,7 +36,6 @@
|
|||
"maketemp": ["MACHE TEMP", "MACHETEMP"],
|
||||
"move" : "NACH",
|
||||
"password" : "PASSWORT",
|
||||
"expel" : "VERTREIBE",
|
||||
"loot" : ["PLÜNDERE", "PLÜNDERN"],
|
||||
"recruit": ["REKRUTIERE", "REKRUTIEREN"],
|
||||
"reserve": ["RESERVIERE", "RESERVIEREN"],
|
||||
|
|
|
@ -47,11 +47,6 @@ if [ ! -s "$ERESSEA/game-$GAME/data/$TURN.dat" ]; then
|
|||
echo "server did not create data for turn $TURN in game $GAME"
|
||||
exit 3
|
||||
fi
|
||||
if [ ! -f "express-$TURN.txt" ]; then
|
||||
if [ -f express.txt ]; then
|
||||
mv express.txt "express-$TURN.txt"
|
||||
fi
|
||||
fi
|
||||
echo "sending reports for game $GAME, turn $TURN"
|
||||
"$BIN/compress.sh" "$GAME" "$TURN"
|
||||
"$BIN/sendreports.sh" "$GAME"
|
||||
|
|
|
@ -4535,6 +4535,13 @@
|
|||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error125" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="error84" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
|
@ -4725,13 +4732,6 @@
|
|||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="feedback_not_inside" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
<arg name="region" type="region"/>
|
||||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
</message>
|
||||
<message name="feedback_unit_not_found" section="errors">
|
||||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- begin main races -->
|
||||
|
||||
<race name="template" maintenance="0" magres="100" maxaura="0" regaura="0" weight="0" capacity="1000" speed="10.0" hp="10" damage="1d4" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" fly="yes" swim="yes" walk="yes" shapeshift="yes" giveperson="yes" giveunit="yes" getitem="yes" recruitethereal="yes" recruitunlimited="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<attack type="1" damage="1d4"/>
|
||||
</race>
|
||||
<race name="lynx" maxaura="0" regaura="0" weight="500" capacity="540" speed="1.0" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" teach="no" getitem="yes">
|
||||
|
@ -32,7 +32,7 @@
|
|||
</race>
|
||||
|
||||
<race name="human" maxaura="1" regaura="1" recruitcost="100" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="other_race" value="elf"/>
|
||||
<skill name="riding" modifier="+1"/>
|
||||
<skill name="shipcraft" modifier="2"/>
|
||||
|
@ -45,7 +45,7 @@
|
|||
</race>
|
||||
|
||||
<race name="orc" studyspeed="-5" magres="-5" maxaura="1" regaura="1" recruitcost="100" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="other_race" value="troll"/>
|
||||
|
||||
<skill name="bow" speed="+5"/>
|
||||
|
@ -76,7 +76,7 @@
|
|||
capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
|
||||
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
|
||||
giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="other_race" value="dwarf"/>
|
||||
<param name="luxury_trade" value="600"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
|
@ -102,7 +102,7 @@
|
|||
<!-- begin secondary races -->
|
||||
|
||||
<race name="demon" magres="15" maxaura="1" regaura="1.1" recruitcost="360" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="30" ac="2" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="cartmaking" modifier="-2"/>
|
||||
<skill name="forestry" modifier="1"/>
|
||||
<skill name="melee" modifier="1"/>
|
||||
|
@ -125,7 +125,7 @@
|
|||
speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
|
||||
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
|
||||
giveunit="yes" getitem="yes" equipment="yes" >
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="armorer" modifier="-1"/>
|
||||
<skill name="bow" modifier="2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
|
@ -143,7 +143,7 @@
|
|||
</race>
|
||||
|
||||
<race name="troll" magres="10" maxaura="1" regaura="1" recruitcost="260" maintenance="10" weight="2000" capacity="1080" speed="1.0" hp="20" ac="1" damage="1d5+3" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="armor.stamina" value="4"/> <!-- +1 natural armor per X levels stamina -->
|
||||
<skill name="armorer" modifier="2"/>
|
||||
<skill name="bow" modifier="-2"/>
|
||||
|
@ -169,7 +169,7 @@
|
|||
speed="1.0" hp="20" damage="1d5" unarmedattack="-2"
|
||||
unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
|
||||
giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="armorer" modifier="2"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
|
@ -598,13 +598,13 @@
|
|||
<attack type="1" damage="1d6"/>
|
||||
</race>
|
||||
<race name="braineater" magres="90" maxaura="1.0" regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
|
||||
<ai splitsize="500" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="500" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="2" damage="3d15"/>
|
||||
<attack type="3" damage="1d1"/>
|
||||
<attack type="4" damage="1d1"/>
|
||||
</race>
|
||||
<race name="toad" magres="20" maxaura="1" regaura="1" maintenance="10" weight="100" capacity="540" speed="1.0" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes" learn="no">
|
||||
<ai splitsize="1"/>
|
||||
<ai splitsize="1" learn="yes"/>
|
||||
<skill name="crossbow" modifier="-10"/>
|
||||
<skill name="mining" modifier="-10"/>
|
||||
<skill name="bow" modifier="-10"/>
|
||||
|
@ -628,7 +628,7 @@
|
|||
<attack type="4" damage="1d2"/>
|
||||
</race>
|
||||
<race name="smurf" weight="1000" capacity="540" speed="1.0" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes" learn="no">
|
||||
<ai splitsize="1"/>
|
||||
<ai splitsize="1" learn="yes"/>
|
||||
<skill name="crossbow" modifier="-10"/>
|
||||
<skill name="mining" modifier="-10"/>
|
||||
<skill name="bow" modifier="-10"/>
|
||||
|
@ -656,13 +656,13 @@
|
|||
<attack type="4" damage="2d40"/>
|
||||
</race>
|
||||
<race name="shadowmaster" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="2.0" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" walk="yes" teach="no" desert="yes">
|
||||
<ai splitsize="50" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="50" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="2d4"/>
|
||||
<attack type="2" damage="2d30"/>
|
||||
<attack type="3" damage="1d2"/>
|
||||
</race>
|
||||
<race name="shadowdemon" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" walk="yes" teach="no" desert="yes" recruitethereal="yes">
|
||||
<ai splitsize="1000" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="1000" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="2d3"/>
|
||||
<attack type="3" damage="1d1"/>
|
||||
</race>
|
||||
|
@ -684,14 +684,14 @@
|
|||
</race>
|
||||
|
||||
<race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="1d6"/>
|
||||
<attack type="4" damage="1d6"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
</race>
|
||||
|
||||
<race name="ent" magres="25" maxaura="1.0" regaura="0.5" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" walk="yes" teach="no">
|
||||
<ai splitsize="1000" moverandom="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="1000" moverandom="yes" learn="yes" scarepeasants="yes"/>
|
||||
<attack type="4" damage="2d12"/>
|
||||
<attack type="4" damage="2d12"/>
|
||||
</race>
|
||||
|
@ -832,7 +832,7 @@
|
|||
</race>
|
||||
|
||||
<race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" swim="yes" teach="no" getitem="yes" resistbash="yes">
|
||||
<ai splitsize="6" scarepeasants="yes" killpeasants="yes" moverandom="yes" moveattack="yes"/>
|
||||
<ai splitsize="6" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes"/>
|
||||
<skill name="tactics" modifier="4"/>
|
||||
<skill name="stealth" modifier="-99"/>
|
||||
<attack type="4" damage="1d30"/>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</race>
|
||||
|
||||
<race name="human" maxaura="1.0" regaura="1.0" recruitcost="75" maintenance="10" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes" migrants="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="trade" modifier="1"/>
|
||||
<skill name="herbalism" modifier="-1"/>
|
||||
<skill name="shipcraft" modifier="1"/>
|
||||
|
@ -579,13 +579,13 @@
|
|||
</race>
|
||||
<race name="braineater" magres="90" maxaura="1.0"
|
||||
regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
|
||||
<ai splitsize="500" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="500" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="2" damage="3d15"/>
|
||||
<attack type="3" damage="1d1"/>
|
||||
<attack type="4" damage="1d1"/>
|
||||
</race>
|
||||
<race name="toad" magres="20" maxaura="1" regaura="1" maintenance="10" weight="100" capacity="540" speed="1" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes" learn="no">
|
||||
<ai splitsize="1"/>
|
||||
<ai splitsize="1" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-10"/>
|
||||
<skill name="crossbow" modifier="-10"/>
|
||||
<skill name="mining" modifier="-10"/>
|
||||
|
@ -617,7 +617,7 @@
|
|||
<attack type="4" damage="1d2"/>
|
||||
</race>
|
||||
<race name="smurf" weight="1000" capacity="540" speed="1" hp="10" damage="1d2" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" giveperson="yes" giveunit="yes" getitem="yes" walk="yes" learn="no">
|
||||
<ai splitsize="1"/>
|
||||
<ai splitsize="1" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-10"/>
|
||||
<skill name="crossbow" modifier="-10"/>
|
||||
<skill name="mining" modifier="-10"/>
|
||||
|
@ -653,13 +653,13 @@
|
|||
<attack type="4" damage="2d40"/>
|
||||
</race>
|
||||
<race name="shadowmaster" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="2.0" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" walk="yes" teach="no" desert="yes">
|
||||
<ai splitsize="50" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="50" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="2d4"/>
|
||||
<attack type="2" damage="2d30"/>
|
||||
<attack type="3" damage="1d2"/>
|
||||
</race>
|
||||
<race name="shadowdemon" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" walk="yes" teach="no" desert="yes" recruitethereal="yes">
|
||||
<ai splitsize="1000" scarepeasants="yes" killpeasants="yes" moverandom="yes"/>
|
||||
<ai splitsize="1000" scarepeasants="yes" killpeasants="yes" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="2d3"/>
|
||||
<attack type="3" damage="1d1"/>
|
||||
</race>
|
||||
|
@ -680,7 +680,7 @@
|
|||
<attack type="1" damage="1d4"/>
|
||||
</race>
|
||||
<race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<attack type="4" damage="1d6"/>
|
||||
<attack type="4" damage="1d6"/>
|
||||
<attack type="1" damage="1d5"/>
|
||||
|
@ -693,12 +693,12 @@
|
|||
<attack type="4" damage="2d40"/>
|
||||
</race>
|
||||
<race name="ent" magres="25" maxaura="1.0" regaura="0.5" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" walk="yes" teach="no">
|
||||
<ai splitsize="1000" moverandom="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="1000" moverandom="yes" learn="yes" scarepeasants="yes"/>
|
||||
<attack type="4" damage="2d12"/>
|
||||
<attack type="4" damage="2d12"/>
|
||||
</race>
|
||||
<race name="wyrm" magres="90" maxaura="1.0" regaura="3.0" weight="18000" capacity="1000000" speed="1.0" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes" unarmedguard="yes">
|
||||
<ai splitsize="1" killpeasants="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="1" killpeasants="yes" learn="yes" scarepeasants="yes"/>
|
||||
<skill name="magic" modifier="12"/>
|
||||
<skill name="tactics" modifier="12"/>
|
||||
<skill name="perception" modifier="10"/>
|
||||
|
@ -708,7 +708,7 @@
|
|||
<attack type="6" spell="powerful_dragonbreath" level="12" />
|
||||
</race>
|
||||
<race name="dragon" magres="70" maxaura="1.0" regaura="2.0" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac="6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
|
||||
<ai splitsize="2" killpeasants="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="2" killpeasants="yes" learn="yes" scarepeasants="yes"/>
|
||||
<skill name="magic" modifier="8"/>
|
||||
<skill name="tactics" modifier="8"/>
|
||||
<skill name="perception" modifier="5"/>
|
||||
|
@ -718,7 +718,7 @@
|
|||
<attack type="6" spell="icy_dragonbreath" level="6" />
|
||||
</race>
|
||||
<race name="youngdragon" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="10000" speed="1.0" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
|
||||
<ai splitsize="6" killpeasants="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="6" killpeasants="yes" learn="yes" scarepeasants="yes"/>
|
||||
<skill name="magic" modifier="4"/>
|
||||
<skill name="tactics" modifier="4"/>
|
||||
<skill name="stealth" modifier="2"/>
|
||||
|
@ -734,7 +734,7 @@
|
|||
<attack type="5"/>
|
||||
</race>
|
||||
<race name="aquarian" maxaura="1" regaura="1" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
<skill name="trade" modifier="2"/>
|
||||
|
@ -752,7 +752,7 @@
|
|||
<familiar race="kraken"/>
|
||||
</race>
|
||||
<race name="cat" maxaura="1" regaura="1" recruitcost="90" maintenance="10" weight="1000" capacity="540" speed="1" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-1"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="building" modifier="-1"/>
|
||||
|
@ -777,7 +777,7 @@
|
|||
<familiar race="hellcat"/>
|
||||
</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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="hunger_damage" value="1d10+7"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
|
@ -809,7 +809,7 @@
|
|||
<familiar race="rat"/>
|
||||
</race>
|
||||
<race name="insect" magres="5" maxaura="1" regaura="1" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="crossbow" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="bow" modifier="-2"/>
|
||||
|
@ -840,7 +840,7 @@
|
|||
maintenance="10" weight="1000" capacity="540" speed="1" hp="50" ac="2" damage="1d5"
|
||||
unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes"
|
||||
giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="2"/>
|
||||
<skill name="trade" modifier="-3"/>
|
||||
<skill name="forestry" modifier="1"/>
|
||||
|
@ -870,7 +870,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="imp"/>
|
||||
</race>
|
||||
<race name="troll" magres="10" maxaura="1" regaura="1" recruitcost="90" maintenance="10" weight="2000" capacity="1080" speed="1" hp="30" ac="1" damage="1d5+3" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="2"/>
|
||||
<skill name="bow" modifier="-2"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
|
@ -900,7 +900,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="wolf"/>
|
||||
</race>
|
||||
<race name="goblin" magres="-5" maxaura="1" regaura="1" recruitcost="40" maintenance="10" weight="600" capacity="440" speed="1" hp="16" damage="1d5" unarmedattack="-2" unarmeddefense="0" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="building" modifier="1"/>
|
||||
|
@ -957,7 +957,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<attack type="1" damage="0d0"/>
|
||||
</race>
|
||||
<race name="template" maintenance="0" magres="100" maxaura="0" regaura="0" weight="0" capacity="1000" speed="10" hp="10" damage="1d4" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" fly="yes" swim="yes" walk="yes" shapeshift="yes" shapeshiftany="yes" giveperson="yes" giveunit="yes" getitem="yes" recruitethereal="yes" recruitunlimited="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<attack type="1" damage="1d4"/>
|
||||
</race>
|
||||
<race name="gnome" magres="100" maxaura="0.0" regaura="0.0" weight="1000" capacity="540" speed="1.0" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" teach="no">
|
||||
|
@ -1075,7 +1075,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<attack type="1" damage="1d1"/>
|
||||
</race>
|
||||
<race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" swim="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
|
||||
<ai splitsize="6" killpeasants="yes" moverandom="yes" moveattack="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="6" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes" scarepeasants="yes"/>
|
||||
<skill name="tactics" modifier="4"/>
|
||||
<attack type="4" damage="1d30"/>
|
||||
<attack type="4" damage="1d30"/>
|
||||
|
@ -1086,7 +1086,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
|
||||
<race name="snotling" magres="-5" maxaura="1" regaura="1"
|
||||
maintenance="10" weight="1000" capacity="540" speed="1" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="no" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
|
||||
<ai splitsize="10000" moverandom="yes"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
<skill name="building" modifier="1"/>
|
||||
|
@ -1115,7 +1115,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="demon"/>
|
||||
</race>
|
||||
<race name="elf" magres="10" maxaura="1" regaura="1.25" recruitcost="130" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="alchemy" modifier="-1"/>
|
||||
<skill name="mining" modifier="-2"/>
|
||||
<skill name="bow" modifier="2"/>
|
||||
|
@ -1141,7 +1141,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="imp"/>
|
||||
</race>
|
||||
<race name="dwarf" magres="5" maxaura="1" regaura="0.5" recruitcost="110" maintenance="10" weight="1000" capacity="540" speed="1" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<skill name="mining" modifier="2"/>
|
||||
<skill name="bow" modifier="-1"/>
|
||||
<skill name="building" modifier="2"/>
|
||||
|
@ -1172,7 +1172,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="rat"/>
|
||||
</race>
|
||||
<race name="orc" studyspeed="-5" magres="-5" maxaura="1" regaura="1" recruitcost="70" maintenance="10" weight="1000" capacity="540" speed="1" 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"/>
|
||||
<ai splitsize="10000" moverandom="yes" learn="yes"/>
|
||||
<param name="recruit_multi" value="0.5"/>
|
||||
<skill name="alchemy" modifier="1"/>
|
||||
<skill name="mining" modifier="1"/>
|
||||
|
@ -1202,7 +1202,7 @@ giveunit="yes" getitem="yes" recruitethereal="yes" equipment="yes">
|
|||
<familiar race="demon"/>
|
||||
</race>
|
||||
<race name="shadowdragon" magres="95" maxaura="1.0" regaura="3.0" weight="100" capacity="100000" speed="1.0" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes">
|
||||
<ai splitsize="1" killpeasants="yes" scarepeasants="yes"/>
|
||||
<ai splitsize="1" killpeasants="yes" learn="yes" scarepeasants="yes"/>
|
||||
<skill name="tactics" modifier="20"/>
|
||||
<skill name="perception" modifier="20"/>
|
||||
<attack type="4" damage="5d30"/>
|
||||
|
|
|
@ -590,9 +590,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletscher
|
|||
msgid "feedback_unit_not_found"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\""
|
||||
|
||||
msgid "feedback_not_inside"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit kontrolliert kein Schiff oder Gebäude.\""
|
||||
|
||||
msgid "error206"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf dem Gebäude liegt bereits so ein Zauber.\""
|
||||
|
||||
|
@ -692,6 +689,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit kan
|
|||
msgid "error85"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Es wurde keine Emailadresse angegeben.\""
|
||||
|
||||
msgid "error125"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - Es wurde kein Banner angegeben.\""
|
||||
|
||||
msgid "starvation"
|
||||
msgstr "\"$unit($unit) verliert in $region($region) $int($dead) von $int($add($live,$dead)) Personen durch Unterernährung.\""
|
||||
|
||||
|
|
|
@ -590,9 +590,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build
|
|||
msgid "feedback_unit_not_found"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\""
|
||||
|
||||
msgid "feedback_unit_not_found"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not the owner of a ship or building.\""
|
||||
|
||||
msgid "error206"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - There is alrady a spell on that building.\""
|
||||
|
||||
|
@ -692,6 +689,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit cannot
|
|||
msgid "error85"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - No email address was supplied.\""
|
||||
|
||||
msgid "error125"
|
||||
msgstr "\"$unit($unit) in $region($region): '$order($command)' - No banner text was supplied.\""
|
||||
|
||||
msgid "starvation"
|
||||
msgstr "\"$unit($unit) loses $int($dead) of $int($add($live,$dead)) people due to starvation in $region($region).\""
|
||||
|
||||
|
|
|
@ -2496,10 +2496,6 @@ msgctxt "keyword"
|
|||
msgid "loot"
|
||||
msgstr "PLÜNDERE"
|
||||
|
||||
msgctxt "keyword"
|
||||
msgid "expel"
|
||||
msgstr "VERTREIBE"
|
||||
|
||||
msgctxt "calendar"
|
||||
msgid "month_1"
|
||||
msgstr "Feldsegen"
|
||||
|
@ -6089,7 +6085,7 @@ msgstr "ENDE"
|
|||
|
||||
msgctxt "raceinfo"
|
||||
msgid "tunnelworm"
|
||||
msgstr "Dieses aus den Tiefen Eresseas stammende gigantische Geschöpf ist dem Leben im Untergrund hervorragend angepasst. Blind, taub und nicht besonders intelligent, aber mit seinen gewaltigen Kräften kann es ganze Berge versetzen oder Wälder roden."
|
||||
msgstr "Diese aus den Tiefen Eresseas stammende gigantische Geschöpf ist dem Leben im Untergrund hervorragend angepasst. Blind, taub und nicht besonders intelligent, aber mit seinen gewaltigen Kräften kann es ganze Berge versetzen oder Wälder roden."
|
||||
|
||||
msgctxt "race"
|
||||
msgid "aquarian_d"
|
||||
|
|
|
@ -2167,10 +2167,6 @@ msgctxt "keyword"
|
|||
msgid "loot"
|
||||
msgstr "loot"
|
||||
|
||||
msgctxt "keyword"
|
||||
msgid "expel"
|
||||
msgstr "EXPEL"
|
||||
|
||||
msgctxt "keyword"
|
||||
msgid "guard"
|
||||
msgstr "GUARD"
|
||||
|
|
|
@ -18,7 +18,7 @@ end
|
|||
local function get_target(param)
|
||||
local ntargets = #targets
|
||||
if ntargets == 0 then
|
||||
eressea.log.error("No tunnel targets for [" .. param .. "]")
|
||||
eressea.log.error("Zero tunnel targets for [" .. param .. "]")
|
||||
return nil
|
||||
end
|
||||
local rn = math.fmod(rng_int(), ntargets)
|
||||
|
@ -31,13 +31,10 @@ end
|
|||
|
||||
local function tunnel_action(b, param)
|
||||
local units = tunnel_travelers(b)
|
||||
local rto = get_target(param)
|
||||
eressea.log.info("Tunnel from " .. tostring(b) .. " [" .. param .. "]")
|
||||
if units then
|
||||
if rto and units then
|
||||
for _, u in pairs(units) do
|
||||
local rto = get_target(param)
|
||||
if not rto then
|
||||
break
|
||||
end
|
||||
u.region = rto
|
||||
eressea.log.info("teleported " .. tostring(u) .. " to " .. tostring(rto))
|
||||
end
|
||||
|
|
|
@ -150,15 +150,13 @@ function process(rules, orders)
|
|||
callbacks(rules, 'update')
|
||||
turn_end() -- ageing, etc.
|
||||
|
||||
if not config.debug then
|
||||
write_files(config.locales)
|
||||
update_scores()
|
||||
write_files(config.locales)
|
||||
update_scores()
|
||||
|
||||
file = '' .. get_turn() .. '.dat'
|
||||
if eressea.write_game(file)~=0 then
|
||||
eressea.log.error("could not write game")
|
||||
return -1
|
||||
end
|
||||
file = '' .. get_turn() .. '.dat'
|
||||
if eressea.write_game(file)~=0 then
|
||||
eressea.log.error("could not write game")
|
||||
return -1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
|
32
src/battle.c
32
src/battle.c
|
@ -3852,6 +3852,10 @@ static void battle_flee(battle * b)
|
|||
int runhp = (int)(0.9 + unit_max_hp(u) * hpflee(u->status));
|
||||
if (runhp > 600) runhp = 600;
|
||||
|
||||
if (u->ship && fval(u->region->terrain, SEA_REGION)) {
|
||||
/* keine Flucht von Schiffen auf hoher See */
|
||||
continue;
|
||||
}
|
||||
if (fval(u_race(u), RCF_UNDEAD) || u_race(u) == get_race(RC_SHADOWKNIGHT)) {
|
||||
/* Untote fliehen nicht. Warum eigentlich? */
|
||||
continue;
|
||||
|
@ -3921,25 +3925,21 @@ void force_leave(region *r, battle *b) {
|
|||
if (u->building) {
|
||||
uo = building_owner(u->building);
|
||||
}
|
||||
else if (u->ship && r->land) {
|
||||
if (u->ship && r->land) {
|
||||
uo = ship_owner(u->ship);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
if (is_enemy(b, uo, u)) {
|
||||
if (leave(u, true)) {
|
||||
message *msg;
|
||||
if (uo->building) {
|
||||
msg = msg_message("force_leave_building", "unit owner building", u, uo, uo->building);
|
||||
}
|
||||
else {
|
||||
msg = msg_message("force_leave_ship", "unit owner ship", u, uo, uo->ship);
|
||||
}
|
||||
add_message(&u->faction->msgs, msg);
|
||||
add_message(&uo->faction->msgs, msg);
|
||||
msg_release(msg);
|
||||
if (uo && is_enemy(b, uo, u)) {
|
||||
message *msg = NULL;
|
||||
if (u->building) {
|
||||
msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building);
|
||||
}
|
||||
else {
|
||||
msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship);
|
||||
}
|
||||
if (msg) {
|
||||
ADDMSG(&u->faction->msgs, msg);
|
||||
}
|
||||
leave(u, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
src/gmtool.c
17
src/gmtool.c
|
@ -854,23 +854,6 @@ static void select_regions(state * st, int selectmode)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (findmode == 'v') {
|
||||
region *r;
|
||||
/* fresh virgin regions */
|
||||
sprintf(sbuffer, "%svirgin", status);
|
||||
statusline(st->wnd_status->handle, sbuffer);
|
||||
for (r = regions; r; r = r->next) {
|
||||
if (r->age == 0) {
|
||||
if (selectmode & MODE_SELECT) {
|
||||
select_coordinate(st->selected, r->x, r->y,
|
||||
selectmode == MODE_SELECT);
|
||||
}
|
||||
else {
|
||||
highlight_region(r, selectmode == MODE_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (findmode == 'c') {
|
||||
region *r;
|
||||
sprintf(sbuffer, "%schaos", status);
|
||||
|
|
11
src/items.c
11
src/items.c
|
@ -292,8 +292,15 @@ struct order *ord)
|
|||
rcfailure = rc_find("toad");
|
||||
}
|
||||
if (rcfailure) {
|
||||
int duration = 2 + rng_int() % 8;
|
||||
change_race(u, duration, rcfailure, NULL);
|
||||
trigger *trestore = trigger_changerace(u, u_race(u), u->irace);
|
||||
if (trestore) {
|
||||
int duration = 2 + rng_int() % 8;
|
||||
|
||||
add_trigger(&u->attribs, "timer", trigger_timeout(duration,
|
||||
trestore));
|
||||
u->irace = NULL;
|
||||
u_setrace(u, rcfailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
|
||||
|
|
|
@ -126,7 +126,7 @@ static void test_get_set_param(CuTest * tc)
|
|||
{
|
||||
struct param *par = 0;
|
||||
test_setup();
|
||||
CuAssertStrEquals(tc, NULL, get_param(par, "foo"));
|
||||
CuAssertStrEquals(tc, 0, get_param(par, "foo"));
|
||||
set_param(&par, "foo", "bar");
|
||||
set_param(&par, "bar", "foo");
|
||||
CuAssertStrEquals(tc, "bar", get_param(par, "foo"));
|
||||
|
|
|
@ -29,10 +29,8 @@ void write_triggers(struct storage *store, const trigger * t)
|
|||
|
||||
int read_triggers(struct gamedata *data, trigger ** tp)
|
||||
{
|
||||
assert(*tp == NULL);
|
||||
for (;;) {
|
||||
trigger_type *ttype;
|
||||
trigger *tr;
|
||||
char zText[128];
|
||||
|
||||
READ_TOK(data->store, zText, sizeof(zText));
|
||||
|
@ -40,43 +38,34 @@ int read_triggers(struct gamedata *data, trigger ** tp)
|
|||
break;
|
||||
ttype = tt_find(zText);
|
||||
assert(ttype || !"unknown trigger-type");
|
||||
tr = t_new(ttype);
|
||||
assert(tr->next == NULL);
|
||||
*tp = t_new(ttype);
|
||||
if (ttype->read) {
|
||||
int i = ttype->read(tr, data);
|
||||
int i = ttype->read(*tp, data);
|
||||
switch (i) {
|
||||
case AT_READ_OK:
|
||||
*tp = tr;
|
||||
tp = &tr->next;
|
||||
tp = &(*tp)->next;
|
||||
break;
|
||||
case AT_READ_FAIL:
|
||||
t_free(tr);
|
||||
free(tr);
|
||||
t_free(*tp);
|
||||
free(*tp);
|
||||
*tp = NULL;
|
||||
break;
|
||||
default:
|
||||
t_free(tr);
|
||||
free(tr);
|
||||
assert(!"invalid return value");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*tp = tr;
|
||||
tp = &tr->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
trigger *t_new(trigger_type *ttype)
|
||||
trigger *t_new(trigger_type * ttype)
|
||||
{
|
||||
trigger *t = calloc(1, sizeof(trigger));
|
||||
if (t) {
|
||||
t->type = ttype;
|
||||
if (ttype->initialize) {
|
||||
ttype->initialize(t);
|
||||
}
|
||||
}
|
||||
if (!t) abort();
|
||||
t->type = ttype;
|
||||
if (ttype->initialize)
|
||||
ttype->initialize(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -538,12 +538,7 @@ const char *faction_getbanner(const faction * f)
|
|||
|
||||
void faction_setbanner(faction * f, const char *banner)
|
||||
{
|
||||
if (banner && banner[0]) {
|
||||
f->banner_id = dbstring_save(banner);
|
||||
}
|
||||
else {
|
||||
f->banner_id = 0;
|
||||
}
|
||||
f->banner_id = dbstring_save(banner);
|
||||
}
|
||||
|
||||
const char *faction_getpassword(const faction *f) {
|
||||
|
@ -664,7 +659,7 @@ void remove_empty_factions(void)
|
|||
for (fp = &factions; *fp;) {
|
||||
faction *f = *fp;
|
||||
|
||||
if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_PAUSED|FFL_NOIDLEOUT)) {
|
||||
if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_NOIDLEOUT)) {
|
||||
destroyfaction(fp);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -406,30 +406,25 @@ item *i_add(item ** pi, item * i)
|
|||
|
||||
void i_merge(item ** pi, item ** si)
|
||||
{
|
||||
if (*pi == NULL) {
|
||||
*pi = *si;
|
||||
}
|
||||
else {
|
||||
item *i = *si;
|
||||
while (i) {
|
||||
item *itmp;
|
||||
while (*pi) {
|
||||
int d = strcmp((*pi)->type->rtype->_name, i->type->rtype->_name);
|
||||
if (d >= 0)
|
||||
break;
|
||||
pi = &(*pi)->next;
|
||||
}
|
||||
if (*pi && (*pi)->type == i->type) {
|
||||
(*pi)->number += i->number;
|
||||
assert((*pi)->number >= 0);
|
||||
i_free(i_remove(&i, i));
|
||||
}
|
||||
else {
|
||||
itmp = i->next;
|
||||
i->next = *pi;
|
||||
*pi = i;
|
||||
i = itmp;
|
||||
}
|
||||
item *i = *si;
|
||||
while (i) {
|
||||
item *itmp;
|
||||
while (*pi) {
|
||||
int d = strcmp((*pi)->type->rtype->_name, i->type->rtype->_name);
|
||||
if (d >= 0)
|
||||
break;
|
||||
pi = &(*pi)->next;
|
||||
}
|
||||
if (*pi && (*pi)->type == i->type) {
|
||||
(*pi)->number += i->number;
|
||||
assert((*pi)->number >= 0);
|
||||
i_free(i_remove(&i, i));
|
||||
}
|
||||
else {
|
||||
itmp = i->next;
|
||||
i->next = *pi;
|
||||
*pi = i;
|
||||
i = itmp;
|
||||
}
|
||||
}
|
||||
*si = NULL;
|
||||
|
|
|
@ -65,43 +65,6 @@ static void test_uchange(CuTest * tc, unit * u, const resource_type * rtype) {
|
|||
test_log_stop(log, sl);
|
||||
}
|
||||
|
||||
void test_merge_items(CuTest *tc)
|
||||
{
|
||||
item *src = NULL, *dst = NULL;
|
||||
const struct item_type *itype, *ihorse;
|
||||
|
||||
test_setup();
|
||||
itype = test_create_itemtype("iron");
|
||||
ihorse = test_create_itemtype("horse");
|
||||
|
||||
i_merge(&dst, &src);
|
||||
CuAssertPtrEquals(tc, NULL, dst);
|
||||
CuAssertPtrEquals(tc, NULL, src);
|
||||
|
||||
i_change(&src, itype, 1);
|
||||
CuAssertIntEquals(tc, 1, i_get(src, itype));
|
||||
i_merge(&dst, &src);
|
||||
CuAssertPtrEquals(tc, NULL, src);
|
||||
CuAssertIntEquals(tc, 1, i_get(dst, itype));
|
||||
|
||||
i_change(&src, itype, 1);
|
||||
CuAssertIntEquals(tc, 1, i_get(src, itype));
|
||||
i_merge(&dst, &src);
|
||||
CuAssertPtrEquals(tc, NULL, src);
|
||||
CuAssertIntEquals(tc, 2, i_get(dst, itype));
|
||||
|
||||
i_change(&src, itype, 1);
|
||||
i_change(&src, ihorse, 1);
|
||||
CuAssertIntEquals(tc, 1, i_get(src, itype));
|
||||
CuAssertIntEquals(tc, 1, i_get(src, ihorse));
|
||||
i_merge(&dst, &src);
|
||||
CuAssertPtrEquals(tc, NULL, src);
|
||||
CuAssertIntEquals(tc, 3, i_get(dst, itype));
|
||||
CuAssertIntEquals(tc, 1, i_get(dst, ihorse));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
void test_change_item(CuTest * tc)
|
||||
{
|
||||
unit * u;
|
||||
|
@ -234,7 +197,6 @@ CuSuite *get_item_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_resourcename_no_appearance);
|
||||
SUITE_ADD_TEST(suite, test_resourcename_with_appearance);
|
||||
SUITE_ADD_TEST(suite, test_merge_items);
|
||||
SUITE_ADD_TEST(suite, test_change_item);
|
||||
SUITE_ADD_TEST(suite, test_get_resource);
|
||||
SUITE_ADD_TEST(suite, test_resource_type);
|
||||
|
|
|
@ -294,6 +294,7 @@ void free_messagelist(mlist *msgs)
|
|||
|
||||
message *add_message(message_list ** pm, message * m)
|
||||
{
|
||||
assert(m && m->type);
|
||||
if (m != NULL) {
|
||||
struct mlist *mnew = malloc(sizeof(struct mlist));
|
||||
if (!mnew) abort();
|
||||
|
|
|
@ -220,16 +220,16 @@ static void test_getstrtoken(CuTest *tc) {
|
|||
CuAssertStrEquals(tc, "durr", getstrtoken());
|
||||
CuAssertStrEquals(tc, "", getstrtoken());
|
||||
CuAssertStrEquals(tc, "", getstrtoken());
|
||||
CuAssertStrEquals(tc, NULL, getstrtoken());
|
||||
CuAssertStrEquals(tc, 0, getstrtoken());
|
||||
init_tokens_str(0);
|
||||
CuAssertStrEquals(tc, NULL, getstrtoken());
|
||||
CuAssertStrEquals(tc, 0, getstrtoken());
|
||||
}
|
||||
|
||||
static void test_skip_token(CuTest *tc) {
|
||||
init_tokens_str("hurr \"durr\"");
|
||||
skip_token();
|
||||
CuAssertStrEquals(tc, "durr", getstrtoken());
|
||||
CuAssertStrEquals(tc, NULL, getstrtoken());
|
||||
CuAssertStrEquals(tc, 0, getstrtoken());
|
||||
}
|
||||
|
||||
static void test_replace_order(CuTest *tc) {
|
||||
|
|
|
@ -218,7 +218,7 @@ extern "C" {
|
|||
#define RCF_ATTACK_MOVED (1<<27) /* may attack if it has moved */
|
||||
#define RCF_MIGRANTS (1<<28) /* may have migrant units (human bonus) */
|
||||
|
||||
#define RCF_DEFAULT (RCF_CANSAIL|RCF_AI_LEARN)
|
||||
#define RCF_DEFAULT RCF_CANSAIL
|
||||
|
||||
/* Economic flags */
|
||||
#define ECF_GIVEPERSON (1<<0) /* Uebergibt Personen */
|
||||
|
|
|
@ -82,6 +82,9 @@
|
|||
#define MAXORDERS 256
|
||||
#define MAXPERSISTENT 128
|
||||
|
||||
/* exported symbols symbols */
|
||||
int g_writegame = 1;
|
||||
|
||||
static void read_alliances(gamedata *data)
|
||||
{
|
||||
storage *store = data->store;
|
||||
|
@ -1770,6 +1773,9 @@ int writegame(const char *filename)
|
|||
stream strm;
|
||||
FILE *F;
|
||||
|
||||
if (g_writegame == 0) {
|
||||
return -1;
|
||||
}
|
||||
create_directories();
|
||||
path_join(datapath(), filename, path, sizeof(path));
|
||||
/* make sure we don't overwrite an existing file (hard links) */
|
||||
|
|
|
@ -23,6 +23,8 @@ extern "C" {
|
|||
* dass hier ein Fehler (fehlende ") vorliegt */
|
||||
|
||||
/* TODO: is this *really* still in use? */
|
||||
extern int g_writegame;
|
||||
|
||||
int readgame(const char *filename);
|
||||
int writegame(const char *filename);
|
||||
|
||||
|
|
|
@ -1218,9 +1218,7 @@ int invisible(const unit * target, const unit * viewer)
|
|||
if (hidden > target->number) hidden = target->number;
|
||||
if (viewer) {
|
||||
const resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
|
||||
if (rtype) {
|
||||
hidden -= i_get(viewer->items, rtype->itype);
|
||||
}
|
||||
hidden -= i_get(viewer->items, rtype->itype);
|
||||
}
|
||||
}
|
||||
return hidden;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#ifndef ERESSEA_VERSION
|
||||
/* the version number, if it was not passed to make with -D */
|
||||
#define ERESSEA_VERSION "3.30.0"
|
||||
#define ERESSEA_VERSION "3.28.0"
|
||||
#endif
|
||||
|
||||
const char *eressea_version(void) {
|
||||
|
|
282
src/laws.c
282
src/laws.c
|
@ -326,7 +326,7 @@ static double peasant_luck_factor(void)
|
|||
return config_get_flt("rules.peasants.peasantluck.factor", PEASANTLUCK);
|
||||
}
|
||||
|
||||
#define ROUND_BIRTHS(growth) (int)ceil(growth)
|
||||
#define ROUND_BIRTHS(growth) ((int)growth)
|
||||
|
||||
int peasant_luck_effect(int peasants, int luck, int maxp, double variance)
|
||||
{
|
||||
|
@ -1335,7 +1335,7 @@ static void remove_idle_players(void)
|
|||
for (fp = &factions; *fp;) {
|
||||
faction *f = *fp;
|
||||
if (!is_monsters(f)) {
|
||||
if (RemoveNMRNewbie() && !fval(f, FFL_PAUSED|FFL_NOIDLEOUT)) {
|
||||
if (RemoveNMRNewbie() && !fval(f, FFL_NOIDLEOUT)) {
|
||||
if (f->age >= 0 && f->age < MAXNEWPLAYERS) {
|
||||
++newbies[f->age];
|
||||
}
|
||||
|
@ -2162,8 +2162,13 @@ int banner_cmd(unit * u, struct order *ord)
|
|||
|
||||
init_order(ord, NULL);
|
||||
s = getstrtoken();
|
||||
faction_setbanner(u->faction, s);
|
||||
ADDMSG(&u->faction->msgs, msg_message("changebanner", "value", s));
|
||||
if (!s || !s[0]) {
|
||||
cmistake(u, ord, 125, MSG_EVENT);
|
||||
}
|
||||
else {
|
||||
faction_setbanner(u->faction, s);
|
||||
ADDMSG(&u->faction->msgs, msg_message("changebanner", "value", s));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3934,12 +3939,11 @@ void init_processor(void)
|
|||
add_proc_global(p, defaultorders, "Defaults setzen");
|
||||
}
|
||||
add_proc_global(p, demographics, "Nahrung, Seuchen, Wachstum, Wanderung");
|
||||
p += 10;
|
||||
|
||||
if (!keyword_disabled(K_SORT)) {
|
||||
add_proc_region(p, do_sort, "Einheiten sortieren");
|
||||
p += 10;
|
||||
add_proc_global(p, restack_units, "Einheiten sortieren");
|
||||
}
|
||||
add_proc_order(p, K_EXPEL, expel_cmd, 0, "Einheiten verjagen");
|
||||
if (!keyword_disabled(K_NUMBER)) {
|
||||
add_proc_order(p, K_NUMBER, renumber_cmd, 0, "Neue Nummern (Einheiten)");
|
||||
p += 10;
|
||||
|
@ -4016,84 +4020,10 @@ void turn_end(void)
|
|||
update_spells();
|
||||
}
|
||||
|
||||
typedef enum cansee_t {
|
||||
CANSEE_DETECTED,
|
||||
CANSEE_HIDDEN,
|
||||
CANSEE_INVISIBLE
|
||||
} cansee_t;
|
||||
|
||||
static enum cansee_t cansee_ex(const unit *u, const region *r, const unit *target, int stealth, int rings)
|
||||
{
|
||||
enum cansee_t result = CANSEE_HIDDEN;
|
||||
if (rings >= target->number) {
|
||||
const resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
|
||||
if (rtype) {
|
||||
int amulet = i_get(u->items, rtype->itype);
|
||||
if (amulet <= 0) {
|
||||
return CANSEE_INVISIBLE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return CANSEE_INVISIBLE;
|
||||
}
|
||||
}
|
||||
if (skill_enabled(SK_PERCEPTION)) {
|
||||
int watch = effskill(u, SK_PERCEPTION, r);
|
||||
if (stealth > watch) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return CANSEE_DETECTED;
|
||||
}
|
||||
|
||||
static bool is_exposed(const unit *u) {
|
||||
return u->building || u->ship || is_guard(u) || leftship(u);
|
||||
}
|
||||
|
||||
static bool big_sea_monster(const unit *u, const region *r) {
|
||||
return ((r->terrain->flags & SEA_REGION) && (u_race(u)->weight >= 5000));
|
||||
}
|
||||
|
||||
bool
|
||||
cansee_unit(const unit * u, const region *r, const unit * target, int modifier)
|
||||
/* r kann != u->region sein, wenn es um durchreisen geht */
|
||||
{
|
||||
int stealth, rings;
|
||||
enum cansee_t see;
|
||||
if (target->number == 0) {
|
||||
return false;
|
||||
}
|
||||
else if (target->faction == u->faction || omniscient(u->faction)) {
|
||||
return true;
|
||||
}
|
||||
else if (is_exposed(target)) {
|
||||
return true;
|
||||
}
|
||||
else if (target->number == 0) {
|
||||
attrib *a = a_find(target->attribs, &at_creator);
|
||||
if (a) {
|
||||
/* u is an empty temporary unit. In this special case we look at the creating unit. */
|
||||
target = (unit *)a->data.v;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stealth = eff_stealth(target, r) - modifier;
|
||||
rings = invisible(target, NULL);
|
||||
see = cansee_ex(u, r, target, stealth, rings);
|
||||
if (CANSEE_HIDDEN == see) {
|
||||
/* bug 2763 and 2754: can see sea serpents on oceans */
|
||||
return big_sea_monster(u, r);
|
||||
}
|
||||
return CANSEE_DETECTED == see;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if unit can be seen by faction.
|
||||
*
|
||||
* @param f -- the observing faction
|
||||
* @param f -- the observiong faction
|
||||
* @param u -- the unit that is observed
|
||||
* @param r -- the region that u is obesrved from (see below)
|
||||
* @param m -- terrain modifier to stealth
|
||||
|
@ -4103,18 +4033,14 @@ cansee_unit(const unit * u, const region *r, const unit * target, int modifier)
|
|||
* Es muss auch niemand aus f in der region sein, wenn sie vom Turm
|
||||
* erblickt wird.
|
||||
*/
|
||||
bool cansee(const faction *f, const region *r, const unit *u, int modifier)
|
||||
bool cansee(const faction * f, const region * r, const unit * u, int modifier)
|
||||
{
|
||||
unit *u2;
|
||||
int rings, stealth;
|
||||
bool bsm, result;
|
||||
int stealth, rings;
|
||||
|
||||
/* quick exits: */
|
||||
if (u->faction == f || omniscient(f)) {
|
||||
return true;
|
||||
}
|
||||
else if (u->number == 0) {
|
||||
/* no need to do this in each cansee_unit: */
|
||||
attrib *a = a_find(u->attribs, &at_creator);
|
||||
if (a) {
|
||||
/* u is an empty temporary unit. In this special case we look at the creating unit. */
|
||||
|
@ -4124,42 +4050,123 @@ bool cansee(const faction *f, const region *r, const unit *u, int modifier)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (is_exposed(u)) {
|
||||
/* obviosuly visibile, we only need a viewer in the region */
|
||||
|
||||
/* simple visibility, just gotta have a viewer in the region to see 'em */
|
||||
if (leftship(u) || is_guard(u) || u->building || u->ship) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rings = invisible(u, NULL);
|
||||
stealth = eff_stealth(u, r) - modifier;
|
||||
|
||||
if (rings < u->number && stealth <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
result = bsm = big_sea_monster(u, r);
|
||||
unit *u2;
|
||||
for (u2 = r->units; u2; u2 = u2->next) {
|
||||
if (u2->faction == f) {
|
||||
enum cansee_t see = cansee_ex(u2, r, u, stealth, rings);
|
||||
if (see == CANSEE_DETECTED) {
|
||||
return true;
|
||||
if (rings < u->number || invisible(u, u2) < u->number) {
|
||||
if (skill_enabled(SK_PERCEPTION)) {
|
||||
int observation = effskill(u2, SK_PERCEPTION, NULL);
|
||||
|
||||
if (observation >= stealth) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (see == CANSEE_HIDDEN && bsm) {
|
||||
return true;
|
||||
}
|
||||
/* still invisible to all: */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
return (rings <= 0 && stealth <= 0);
|
||||
}
|
||||
|
||||
bool cansee_unit(const unit * u, const unit * target, int modifier)
|
||||
/* target->region kann != u->region sein, wenn es um durchreisen geht */
|
||||
{
|
||||
if (target->number == 0)
|
||||
return false;
|
||||
else if (target->faction == u->faction)
|
||||
return true;
|
||||
else {
|
||||
int n, rings;
|
||||
|
||||
if (is_guard(target) || target->building
|
||||
|| target->ship) {
|
||||
return true;
|
||||
}
|
||||
|
||||
n = eff_stealth(target, target->region) - modifier;
|
||||
rings = invisible(target, NULL);
|
||||
if (rings == 0 && n <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rings && invisible(target, u) >= target->number) {
|
||||
return false;
|
||||
}
|
||||
if (skill_enabled(SK_PERCEPTION)) {
|
||||
int o = effskill(u, SK_PERCEPTION, target->region);
|
||||
if (o >= n) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
cansee_durchgezogen(const faction * f, const region * r, const unit * u,
|
||||
int modifier)
|
||||
/* r kann != u->region sein, wenn es um durchreisen geht */
|
||||
/* und es muss niemand aus f in der region sein, wenn sie vom Turm
|
||||
* erblickt wird */
|
||||
{
|
||||
unit *u2;
|
||||
|
||||
if (u->number == 0)
|
||||
return false;
|
||||
else if (u->faction == f)
|
||||
return true;
|
||||
else {
|
||||
int rings, n;
|
||||
|
||||
if (is_guard(u) || u->building || u->ship) {
|
||||
return true;
|
||||
}
|
||||
|
||||
n = eff_stealth(u, r) - modifier;
|
||||
rings = invisible(u, NULL);
|
||||
if (rings == 0 && n <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (u2 = r->units; u2; u2 = u2->next) {
|
||||
if (u2->faction == f) {
|
||||
int o;
|
||||
|
||||
if (rings && invisible(u, u2) >= u->number)
|
||||
continue;
|
||||
|
||||
o = effskill(u2, SK_PERCEPTION, NULL);
|
||||
|
||||
if (o >= n) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
seefaction(const faction * f, const region * r, const unit * u, int modifier)
|
||||
{
|
||||
if (((f == u->faction) || !fval(u, UFL_ANON_FACTION))
|
||||
&& cansee(f, r, u, modifier)) {
|
||||
&& cansee(f, r, u, modifier))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4180,66 +4187,3 @@ int locale_cmd(unit * u, order * ord)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void expel_building(unit *u, unit *u2, order *ord) {
|
||||
building *b = u->building;
|
||||
|
||||
if (u != building_owner(b)) {
|
||||
/* error: must be the owner */
|
||||
cmistake(u, ord, 5, MSG_EVENT);
|
||||
}
|
||||
else {
|
||||
if (leave(u2, true)) {
|
||||
message *msg = msg_message("force_leave_building", "owner unit building", u, u2, u->building);
|
||||
add_message(&u->faction->msgs, msg);
|
||||
add_message(&u2->faction->msgs, msg);
|
||||
msg_release(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void expel_ship(unit *u, unit *u2, order *ord) {
|
||||
ship *sh = u->ship;
|
||||
if (u != ship_owner(sh)) {
|
||||
/* error: must be the owner */
|
||||
cmistake(u, ord, 146, MSG_EVENT);
|
||||
}
|
||||
else if (!u->region->land) {
|
||||
/* error: must not be at sea */
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, ord, "error_onlandonly", NULL));
|
||||
}
|
||||
else {
|
||||
if (leave(u2, true)) {
|
||||
message *msg = msg_message("force_leave_ship", "owner unit ship", u, u2, u->ship);
|
||||
add_message(&u->faction->msgs, msg);
|
||||
add_message(&u2->faction->msgs, msg);
|
||||
msg_release(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int expel_cmd(unit *u, order *ord) {
|
||||
faction *f = u->faction;
|
||||
unit *u2;
|
||||
init_order(ord, f->locale);
|
||||
getunit(u->region, u->faction, &u2);
|
||||
if (u2 == NULL) {
|
||||
/* error: target unit not found */
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, ord, "feedback_unit_not_found", NULL));
|
||||
return 0;
|
||||
}
|
||||
if (u->building) {
|
||||
expel_building(u, u2, ord);
|
||||
}
|
||||
else if (u->ship) {
|
||||
expel_ship(u, u2, ord);
|
||||
}
|
||||
else {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, ord, "feedback_not_inside", NULL));
|
||||
/* error: unit must be owner of a ship or building */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ extern "C" {
|
|||
bool long_order_allowed(const struct unit *u, bool flags_only);
|
||||
bool password_wellformed(const char *password);
|
||||
|
||||
int expel_cmd(struct unit *u, struct order *ord);
|
||||
int locale_cmd(struct unit *u, struct order *ord);
|
||||
int password_cmd(struct unit *u, struct order *ord);
|
||||
int banner_cmd(struct unit *u, struct order *ord);
|
||||
|
@ -86,7 +85,9 @@ extern "C" {
|
|||
|
||||
bool cansee(const struct faction * f, const struct region * r,
|
||||
const struct unit *u, int modifier);
|
||||
bool cansee_unit(const struct unit *u, const struct region *r, const struct unit *who,
|
||||
bool cansee_durchgezogen(const struct faction *f, const struct region *r,
|
||||
const struct unit *u, int modifier);
|
||||
bool cansee_unit(const struct unit *u, const struct unit *target,
|
||||
int modifier);
|
||||
bool seefaction(const struct faction *f, const struct region *r,
|
||||
const struct unit *u, int modifier);
|
||||
|
|
159
src/laws.test.c
159
src/laws.test.c
|
@ -173,95 +173,6 @@ static void test_enter_ship(CuTest * tc)
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_expel_building(CuTest *tc) {
|
||||
unit *u1, *u2;
|
||||
order *ord;
|
||||
building *b;
|
||||
|
||||
test_setup();
|
||||
u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0));
|
||||
u2 = test_create_unit(test_create_faction(), u1->region);
|
||||
ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no));
|
||||
|
||||
expel_cmd(u2, ord);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside"));
|
||||
test_clear_messages(u2->faction);
|
||||
|
||||
b = u2->building = u1->building = test_create_building(u1->region, NULL);
|
||||
CuAssertPtrEquals(tc, u1, building_owner(b));
|
||||
|
||||
expel_cmd(u2, ord);
|
||||
/* Nothing happened: */
|
||||
CuAssertPtrEquals(tc, u1, building_owner(b));
|
||||
CuAssertPtrEquals(tc, b, u1->building);
|
||||
CuAssertPtrEquals(tc, b, u2->building);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error5"));
|
||||
test_clear_messages(u1->faction);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
|
||||
expel_cmd(u1, ord);
|
||||
/* owner has expelled u2: */
|
||||
CuAssertPtrEquals(tc, NULL, u2->building);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_building"));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_building"));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_expel_ship(CuTest *tc) {
|
||||
unit *u1, *u2;
|
||||
order *ord;
|
||||
ship *sh;
|
||||
|
||||
test_setup();
|
||||
u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0));
|
||||
u2 = test_create_unit(test_create_faction(), u1->region);
|
||||
ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no));
|
||||
expel_cmd(u2, ord);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside"));
|
||||
test_clear_messages(u2->faction);
|
||||
|
||||
sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL);
|
||||
CuAssertPtrEquals(tc, u1, ship_owner(sh));
|
||||
|
||||
expel_cmd(u2, ord);
|
||||
/* Nothing happened: */
|
||||
CuAssertPtrEquals(tc, u1, ship_owner(sh));
|
||||
CuAssertPtrEquals(tc, sh, u1->ship);
|
||||
CuAssertPtrEquals(tc, sh, u2->ship);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error146"));
|
||||
test_clear_messages(u2->faction);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
|
||||
expel_cmd(u1, ord);
|
||||
/* owner has expelled u2: */
|
||||
CuAssertPtrEquals(tc, NULL, u2->ship);
|
||||
CuAssertPtrEquals(tc, sh, leftship(u2));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_ship"));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_ship"));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_expel_ship_at_sea(CuTest *tc) {
|
||||
unit *u1, *u2;
|
||||
order *ord;
|
||||
ship *sh;
|
||||
|
||||
test_setup();
|
||||
u1 = test_create_unit(test_create_faction(), test_create_ocean(0, 0));
|
||||
u2 = test_create_unit(test_create_faction(), u1->region);
|
||||
sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL);
|
||||
CuAssertPtrEquals(tc, u1, ship_owner(sh));
|
||||
|
||||
ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no));
|
||||
expel_cmd(u1, ord);
|
||||
/* owner has not expelled u2: */
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "error_onlandonly"));
|
||||
CuAssertPtrEquals(tc, sh, u2->ship);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_display_cmd(CuTest *tc) {
|
||||
unit *u;
|
||||
faction *f;
|
||||
|
@ -1312,6 +1223,7 @@ static void test_banner_cmd(CuTest *tc) {
|
|||
order *ord;
|
||||
|
||||
test_setup();
|
||||
mt_create_error(125);
|
||||
mt_create_va(mt_new("changebanner", NULL), "value:string", MT_NEW_END);
|
||||
u = test_create_unit(f = test_create_faction(), test_create_region(0, 0, NULL));
|
||||
|
||||
|
@ -1324,8 +1236,8 @@ static void test_banner_cmd(CuTest *tc) {
|
|||
|
||||
ord = create_order(K_BANNER, f->locale, NULL);
|
||||
banner_cmd(u, ord);
|
||||
CuAssertStrEquals(tc, NULL, faction_getbanner(f));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "changebanner"));
|
||||
CuAssertStrEquals(tc, "Hodor!", faction_getbanner(f));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error125"));
|
||||
free_order(ord);
|
||||
test_clear_messages(f);
|
||||
|
||||
|
@ -1897,37 +1809,32 @@ static void test_cansee(CuTest *tc) {
|
|||
|
||||
static void test_cansee_ring(CuTest *tc) {
|
||||
unit *u, *u2;
|
||||
item_type *iring, *isee;
|
||||
item_type *itype[2];
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(), test_create_region(0, 0, NULL));
|
||||
u2 = test_create_unit(test_create_faction(), u->region);
|
||||
scale_number(u2, 2);
|
||||
|
||||
iring = test_create_itemtype("roi");
|
||||
isee = test_create_itemtype("aots");
|
||||
itype[0] = test_create_itemtype("roi");
|
||||
itype[1] = test_create_itemtype("aots");
|
||||
CuAssertPtrNotNull(tc, get_resourcetype(R_RING_OF_INVISIBILITY));
|
||||
CuAssertPtrEquals(tc, iring->rtype, (void *)get_resourcetype(R_RING_OF_INVISIBILITY));
|
||||
CuAssertPtrEquals(tc, itype[0]->rtype, (void *)get_resourcetype(R_RING_OF_INVISIBILITY));
|
||||
CuAssertPtrNotNull(tc, get_resourcetype(R_AMULET_OF_TRUE_SEEING));
|
||||
CuAssertPtrEquals(tc, isee->rtype, (void *)get_resourcetype(R_AMULET_OF_TRUE_SEEING));
|
||||
CuAssertPtrEquals(tc, itype[1]->rtype, (void *)get_resourcetype(R_AMULET_OF_TRUE_SEEING));
|
||||
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
|
||||
/* a single ring hides one person, but not two: */
|
||||
i_change(&u2->items, iring, 1);
|
||||
CuAssertTrue(tc, !cansee(u->faction, u->region, u2, 0));
|
||||
scale_number(u2, 2);
|
||||
/* a single ring is not enough to hide two people */
|
||||
i_change(&u2->items, itype[0], 1);
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
|
||||
/* two rings can hide two people */
|
||||
i_change(&u2->items, iring, 1);
|
||||
i_change(&u2->items, itype[0], 1);
|
||||
CuAssertTrue(tc, !cansee(u->faction, u->region, u2, 0));
|
||||
|
||||
/* one amulet negates one of the two rings */
|
||||
i_change(&u->items, isee, 1);
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
|
||||
/* having more rings than people doesn't help: */
|
||||
i_change(&u2->items, iring, 1);
|
||||
i_change(&u->items, itype[1], 1);
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
|
||||
test_teardown();
|
||||
|
@ -1966,42 +1873,6 @@ static void test_cansee_sphere(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hidden monsters are seen in oceans if they are big enough.
|
||||
*/
|
||||
static void test_cansee_monsters(CuTest *tc) {
|
||||
unit *u, *u2;
|
||||
race *rc;
|
||||
const item_type *itype;
|
||||
|
||||
test_setup();
|
||||
itype = test_create_itemtype("roi");
|
||||
u = test_create_unit(test_create_faction(), test_create_ocean(0, 0));
|
||||
u2 = test_create_unit(test_create_faction(), u->region);
|
||||
rc = test_create_race("seaserpent");
|
||||
rc->weight = 4999;
|
||||
u_setrace(u2, rc);
|
||||
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 2));
|
||||
|
||||
set_level(u2, SK_STEALTH, 1);
|
||||
CuAssertTrue(tc, !cansee(u->faction, u->region, u2, 0));
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 1));
|
||||
|
||||
rc->weight = 5000;
|
||||
/* no stealth for fatties at sea */
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 0));
|
||||
CuAssertTrue(tc, cansee(u->faction, u->region, u2, 1));
|
||||
|
||||
/* rings still work */
|
||||
i_change(&u2->items, itype, 1);
|
||||
CuAssertTrue(tc, !cansee(u->faction, u->region, u2, 0));
|
||||
CuAssertTrue(tc, !cansee(u->faction, u->region, u2, 2));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_nmr_timeout(CuTest *tc) {
|
||||
test_setup();
|
||||
CuAssertIntEquals(tc, 0, NMRTimeout());
|
||||
|
@ -2449,9 +2320,6 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_enter_building);
|
||||
SUITE_ADD_TEST(suite, test_enter_ship);
|
||||
SUITE_ADD_TEST(suite, test_display_cmd);
|
||||
SUITE_ADD_TEST(suite, test_expel_building);
|
||||
SUITE_ADD_TEST(suite, test_expel_ship);
|
||||
SUITE_ADD_TEST(suite, test_expel_ship_at_sea);
|
||||
SUITE_ADD_TEST(suite, test_rule_force_leave);
|
||||
SUITE_ADD_TEST(suite, test_force_leave_buildings);
|
||||
SUITE_ADD_TEST(suite, test_force_leave_ships);
|
||||
|
@ -2474,7 +2342,6 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_cansee);
|
||||
SUITE_ADD_TEST(suite, test_cansee_ring);
|
||||
SUITE_ADD_TEST(suite, test_cansee_sphere);
|
||||
SUITE_ADD_TEST(suite, test_cansee_monsters);
|
||||
SUITE_ADD_TEST(suite, test_nmr_timeout);
|
||||
SUITE_ADD_TEST(suite, test_long_orders);
|
||||
SUITE_ADD_TEST(suite, test_long_order_on_ocean);
|
||||
|
|
39
src/magic.c
39
src/magic.c
|
@ -1273,12 +1273,10 @@ static void do_fumble(castorder * co)
|
|||
unit *caster = co_get_caster(co);
|
||||
const spell *sp = co->sp;
|
||||
int level = co->level;
|
||||
int duration;
|
||||
double effect;
|
||||
static int rc_cache;
|
||||
static const race *rc_toad = NULL;
|
||||
fumble_f fun;
|
||||
trigger *trestore;
|
||||
int duration;
|
||||
|
||||
ADDMSG(&caster->faction->msgs,
|
||||
msg_message("patzer", "unit region spell", caster, r, sp));
|
||||
|
@ -1295,26 +1293,32 @@ static void do_fumble(castorder * co)
|
|||
break;
|
||||
|
||||
case 1: /* toad */
|
||||
/* one or two things will happen: the toad changes its race back,
|
||||
{
|
||||
/* one or two things will happen: the toad changes her race back,
|
||||
* and may or may not get toadslime.
|
||||
* The list of things to happen are attached to a timeout
|
||||
* trigger and that's added to the triggerlist of the mage gone toad.
|
||||
* trigger and that's added to the triggerlit of the mage gone toad.
|
||||
*/
|
||||
static const race *rc_toad;
|
||||
trigger *trestore = trigger_changerace(mage, u_race(mage), mage->irace);
|
||||
if (chance(0.7)) {
|
||||
const resource_type *rtype = rt_find("toadslime");
|
||||
if (rtype) {
|
||||
t_add(&trestore, trigger_giveitem(mage, rtype->itype, 1));
|
||||
}
|
||||
}
|
||||
duration = rng_int() % level / 2;
|
||||
if (duration < 2) duration = 2;
|
||||
add_trigger(&mage->attribs, "timer", trigger_timeout(duration, trestore));
|
||||
if (rc_changed(&rc_cache)) {
|
||||
rc_toad = get_race(RC_TOAD);
|
||||
}
|
||||
duration = rng_int() % level / 2;
|
||||
trestore = change_race(mage, duration, rc_toad, NULL);
|
||||
if (trestore) {
|
||||
if (chance(0.7)) {
|
||||
const resource_type *rtype = rt_find("toadslime");
|
||||
if (rtype) {
|
||||
t_add(&trestore, trigger_giveitem(mage, rtype->itype, 1));
|
||||
}
|
||||
}
|
||||
ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", mage, r, sp));
|
||||
}
|
||||
u_setrace(mage, rc_toad);
|
||||
mage->irace = NULL;
|
||||
ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", mage, r, sp));
|
||||
break;
|
||||
}
|
||||
/* fall-through is intentional! */
|
||||
|
||||
case 2:
|
||||
/* temporary skill loss */
|
||||
|
@ -1326,7 +1330,6 @@ static void do_fumble(castorder * co)
|
|||
c->data.i = SK_MAGIC;
|
||||
ADDMSG(&caster->faction->msgs, msg_message("patzer2", "unit region", caster, r));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
/* Spruch schlaegt fehl, alle Magiepunkte weg */
|
||||
|
@ -2578,7 +2581,7 @@ static castorder *cast_cmd(unit * u, order * ord)
|
|||
skill = limit;
|
||||
}
|
||||
sp = unit_getspell(mage, s, mage->faction->locale);
|
||||
if (sp == NULL || sp->sptyp & NOTFAMILIARCAST) {
|
||||
if (sp->sptyp & NOTFAMILIARCAST) {
|
||||
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
|
||||
cmistake(u, ord, 177, MSG_MAGIC);
|
||||
return 0;
|
||||
|
|
|
@ -200,7 +200,7 @@ static int parse_args(int argc, char **argv)
|
|||
const char *arg;
|
||||
switch (argi[1]) {
|
||||
case 'D':
|
||||
config_set("config.debug", "1");
|
||||
g_writegame = 0;
|
||||
break;
|
||||
case 'c':
|
||||
i = get_arg(argc, argv, 2, i, &arg, 0);
|
||||
|
|
|
@ -258,7 +258,7 @@ get_island_info(region * root, int *size_p, int *inhabited_p, int *maxage_p)
|
|||
if (r->units) {
|
||||
unit *u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (!fval(u->faction, FFL_PAUSED | FFL_NOIDLEOUT) && u->faction->age > maxage) {
|
||||
if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) {
|
||||
maxage = u->faction->age;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -763,17 +763,12 @@ void monster_cannibalism(unit *u)
|
|||
|
||||
for (u2 = u->next; u2; u2 = u2->next) {
|
||||
if (u2->_race == u->_race) {
|
||||
i_merge(&u->items, &u2->items);
|
||||
stats_count("monsters.cannibalism", u2->number);
|
||||
u2->number = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool monster_can_learn(const race *rc) {
|
||||
return (rc->flags & (RCF_NOLEARN|RCF_AI_LEARN)) == RCF_AI_LEARN;
|
||||
}
|
||||
|
||||
void plan_monsters(faction * f)
|
||||
{
|
||||
region *r;
|
||||
|
@ -874,7 +869,7 @@ void plan_monsters(faction * f)
|
|||
long_order = create_order(K_PIRACY, f->locale, NULL);
|
||||
}
|
||||
else {
|
||||
if (monster_can_learn(rc)) {
|
||||
if (rc->flags & RCF_AI_LEARN) {
|
||||
long_order = monster_learn(u);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,55 +95,51 @@ static void handle_unit(void *userData, int no) {
|
|||
|
||||
static void handle_order(void *userData, const char *str) {
|
||||
parser_state *state = (parser_state *)userData;
|
||||
const char * tok, *input;
|
||||
const char * tok, *input = str;
|
||||
char buffer[64];
|
||||
const struct locale *lang;
|
||||
param_t p;
|
||||
faction * f = state->f;
|
||||
|
||||
lang = f ? f->locale : default_locale;
|
||||
ltrim(&str);
|
||||
if (*str == 0) return;
|
||||
input = str;
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
if (tok) {
|
||||
param_t p = findparam(tok, lang);
|
||||
if (p == P_FACTION || p == P_GAMENAME) {
|
||||
p = findparam(tok, lang);
|
||||
if (p == P_FACTION || p == P_GAMENAME) {
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
if (tok) {
|
||||
int no = atoi36(tok);
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
if (tok) {
|
||||
int no = atoi36(tok);
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
handle_faction(userData, no, tok);
|
||||
}
|
||||
else {
|
||||
/* TODO: log_error() */
|
||||
}
|
||||
handle_faction(userData, no, tok);
|
||||
}
|
||||
else if (p == P_UNIT) {
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
if (tok) {
|
||||
int no = atoi36(tok);
|
||||
handle_unit(userData, no);
|
||||
}
|
||||
else {
|
||||
/* TODO: log_error() */
|
||||
}
|
||||
else if (p == P_NEXT) {
|
||||
state->f = NULL;
|
||||
state->u = NULL;
|
||||
state->next_order = NULL;
|
||||
}
|
||||
else if (p == P_UNIT) {
|
||||
tok = parse_token(&input, buffer, sizeof(buffer));
|
||||
if (tok) {
|
||||
int no = atoi36(tok);
|
||||
handle_unit(userData, no);
|
||||
}
|
||||
else if (p == P_REGION) {
|
||||
state->u = NULL;
|
||||
state->next_order = NULL;
|
||||
}
|
||||
else if (p == P_NEXT) {
|
||||
state->f = NULL;
|
||||
state->u = NULL;
|
||||
state->next_order = NULL;
|
||||
}
|
||||
else if (p == P_REGION) {
|
||||
state->u = NULL;
|
||||
state->next_order = NULL;
|
||||
}
|
||||
else if (state->u) {
|
||||
unit * u = state->u;
|
||||
order * ord = parse_order(str, lang);
|
||||
if (ord) {
|
||||
*state->next_order = ord;
|
||||
state->next_order = &ord->next;
|
||||
}
|
||||
else if (state->u) {
|
||||
unit *u = state->u;
|
||||
order *ord = parse_order(str, lang);
|
||||
if (ord) {
|
||||
*state->next_order = ord;
|
||||
state->next_order = &ord->next;
|
||||
}
|
||||
else {
|
||||
ADDMSG(&u->faction->msgs, msg_message("parse_error", "unit command", u, str));
|
||||
}
|
||||
else {
|
||||
ADDMSG(&u->faction->msgs, msg_message("parse_error", "unit command", u, str));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2203,10 +2203,6 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
}
|
||||
}
|
||||
}
|
||||
else while (u && u->building) {
|
||||
/* do not report units in buildings */
|
||||
u = u->next;
|
||||
}
|
||||
while (u && !u->ship) {
|
||||
if (visible_unit(u, f, stealthmod, r->seen.mode)) {
|
||||
nr_unit(out, f, u, 4, r->seen.mode);
|
||||
|
|
|
@ -1045,7 +1045,7 @@ static void cb_add_address(region *r, unit *ut, void *cbdata) {
|
|||
for (u = r->units; u; u = u->next) {
|
||||
faction *sf = visible_faction(f, u);
|
||||
assert(u->faction != f); /* if this is see_travel only, then I shouldn't be here. */
|
||||
if (data->lastf != sf && cansee_unit(ut, r, u, data->stealthmod)) {
|
||||
if (data->lastf != sf && cansee_unit(ut, u, data->stealthmod)) {
|
||||
add_seen_faction_i(data->flist, sf);
|
||||
data->lastf = sf;
|
||||
}
|
||||
|
@ -2361,7 +2361,7 @@ static void count_cb(region *r, unit *u, void *cbdata) {
|
|||
count_data *data = (count_data *)cbdata;
|
||||
const struct faction *f = data->f;
|
||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||
if (cansee(f, r, u, 0)) {
|
||||
if (cansee_durchgezogen(f, r, u, 0)) {
|
||||
++data->n;
|
||||
}
|
||||
}
|
||||
|
@ -2379,8 +2379,15 @@ bool visible_unit(const unit *u, const faction *f, int stealthmod, seen_mode mod
|
|||
if (u->faction == f) {
|
||||
return true;
|
||||
}
|
||||
else if (mode >= seen_lighthouse && stealthmod > INT_MIN) {
|
||||
return cansee(f, u->region, u, stealthmod);
|
||||
else if (mode >= seen_lighthouse) {
|
||||
if (stealthmod > INT_MIN) {
|
||||
if ((u->region->terrain->flags & SEA_REGION) && (u_race(u)->weight >= 5000)) {
|
||||
return true;
|
||||
}
|
||||
if (mode >= seen_travel || u->building || u->ship || is_guard(u)) {
|
||||
return cansee(f, u->region, u, stealthmod);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
191
src/sort.c
191
src/sort.c
|
@ -13,7 +13,7 @@
|
|||
#include "util/param.h"
|
||||
#include "util/parser.h"
|
||||
|
||||
static void sort_before(unit *v, unit **up) {
|
||||
void sort_before(unit *v, unit **up) {
|
||||
unit *u = *up;
|
||||
region *r = u->region;
|
||||
unit **vp = &r->units;
|
||||
|
@ -24,107 +24,102 @@ static void sort_before(unit *v, unit **up) {
|
|||
u->next = v;
|
||||
}
|
||||
|
||||
void do_sort(region *r)
|
||||
{
|
||||
unit **up = &r->units;
|
||||
bool sorted = false;
|
||||
while (*up) {
|
||||
unit *u = *up;
|
||||
if (!fval(u, UFL_MARK) && !is_paused(u->faction)) {
|
||||
struct order *ord;
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
if (getkeyword(ord) == K_SORT) {
|
||||
char token[128];
|
||||
const char *s;
|
||||
param_t p;
|
||||
int id;
|
||||
unit *v;
|
||||
|
||||
init_order(ord, NULL);
|
||||
s = gettoken(token, sizeof(token));
|
||||
p = findparam(s, u->faction->locale);
|
||||
id = getid();
|
||||
v = findunit(id);
|
||||
|
||||
if (v == u) {
|
||||
syntax_error(u, ord);
|
||||
}
|
||||
else if (!v || v->region != r) {
|
||||
cmistake(u, ord, 258, MSG_EVENT);
|
||||
}
|
||||
else if (v->faction != u->faction && !is_paused(v->faction)) {
|
||||
cmistake(u, ord, 258, MSG_EVENT);
|
||||
}
|
||||
else if (v->building != u->building || v->ship != u->ship) {
|
||||
cmistake(u, ord, 259, MSG_EVENT);
|
||||
}
|
||||
else if (u->building && building_owner(u->building) == u) {
|
||||
cmistake(u, ord, 260, MSG_EVENT);
|
||||
}
|
||||
else if (u->ship && ship_owner(u->ship) == u) {
|
||||
cmistake(u, ord, 260, MSG_EVENT);
|
||||
}
|
||||
else {
|
||||
switch (p) {
|
||||
case P_AFTER:
|
||||
*up = u->next;
|
||||
u->next = v->next;
|
||||
v->next = u;
|
||||
fset(u, UFL_MARK);
|
||||
sorted = true;
|
||||
break;
|
||||
case P_BEFORE:
|
||||
if (v->ship && ship_owner(v->ship) == v) {
|
||||
if (is_paused(v->faction)) {
|
||||
sort_before(v, up);
|
||||
ship_set_owner(u);
|
||||
}
|
||||
else {
|
||||
cmistake(v, ord, 261, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (v->building && building_owner(v->building) == v) {
|
||||
if (is_paused(v->faction)) {
|
||||
sort_before(v, up);
|
||||
building_set_owner(u);
|
||||
}
|
||||
else {
|
||||
cmistake(v, ord, 261, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sort_before(v, up);
|
||||
}
|
||||
fset(u, UFL_MARK);
|
||||
sorted = true;
|
||||
break;
|
||||
default:
|
||||
/* TODO: syntax error message? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (u == *up)
|
||||
up = &u->next;
|
||||
}
|
||||
if (sorted) {
|
||||
unit *u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
freset(u, UFL_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void restack_units(void)
|
||||
{
|
||||
region *r;
|
||||
for (r = regions; r; r = r->next) {
|
||||
do_sort(r);
|
||||
unit **up = &r->units;
|
||||
bool sorted = false;
|
||||
while (*up) {
|
||||
unit *u = *up;
|
||||
if (!fval(u, UFL_MARK) && !is_paused(u->faction)) {
|
||||
struct order *ord;
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
if (getkeyword(ord) == K_SORT) {
|
||||
char token[128];
|
||||
const char *s;
|
||||
param_t p;
|
||||
int id;
|
||||
unit *v;
|
||||
|
||||
init_order(ord, NULL);
|
||||
s = gettoken(token, sizeof(token));
|
||||
p = findparam(s, u->faction->locale);
|
||||
id = getid();
|
||||
v = findunit(id);
|
||||
|
||||
if (v == u) {
|
||||
syntax_error(u, ord);
|
||||
}
|
||||
else if (!v || v->region != r) {
|
||||
cmistake(u, ord, 258, MSG_EVENT);
|
||||
}
|
||||
else if (v->faction != u->faction && !is_paused(v->faction)) {
|
||||
cmistake(u, ord, 258, MSG_EVENT);
|
||||
}
|
||||
else if (v->building != u->building || v->ship != u->ship) {
|
||||
cmistake(u, ord, 259, MSG_EVENT);
|
||||
}
|
||||
else if (u->building && building_owner(u->building) == u) {
|
||||
cmistake(u, ord, 260, MSG_EVENT);
|
||||
}
|
||||
else if (u->ship && ship_owner(u->ship) == u) {
|
||||
cmistake(u, ord, 260, MSG_EVENT);
|
||||
}
|
||||
else {
|
||||
switch (p) {
|
||||
case P_AFTER:
|
||||
*up = u->next;
|
||||
u->next = v->next;
|
||||
v->next = u;
|
||||
fset(u, UFL_MARK);
|
||||
sorted = true;
|
||||
break;
|
||||
case P_BEFORE:
|
||||
if (v->ship && ship_owner(v->ship) == v) {
|
||||
if (is_paused(v->faction)) {
|
||||
sort_before(v, up);
|
||||
ship_set_owner(u);
|
||||
}
|
||||
else {
|
||||
cmistake(v, ord, 261, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (v->building && building_owner(v->building) == v) {
|
||||
if (is_paused(v->faction)) {
|
||||
sort_before(v, up);
|
||||
building_set_owner(u);
|
||||
}
|
||||
else {
|
||||
cmistake(v, ord, 261, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sort_before(v, up);
|
||||
}
|
||||
fset(u, UFL_MARK);
|
||||
sorted = true;
|
||||
break;
|
||||
default:
|
||||
/* TODO: syntax error message? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (u == *up)
|
||||
up = &u->next;
|
||||
}
|
||||
if (sorted) {
|
||||
unit *u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
freset(u, UFL_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
struct region;
|
||||
|
||||
void restack_units(void);
|
||||
void do_sort(struct region *r);
|
||||
|
|
17
src/spells.c
17
src/spells.c
|
@ -500,10 +500,7 @@ static const race *select_familiar(const race * magerace, int level, magic_t mag
|
|||
return rcfixed;
|
||||
}
|
||||
|
||||
if (magerace->familiars[0] == NULL) {
|
||||
log_error("a %s magician is trying to summon a familiar", magerace->_name);
|
||||
return NULL;
|
||||
}
|
||||
assert(magerace->familiars[0]);
|
||||
if (rnd >= 100 - (level * 5)) {
|
||||
retval = magerace->familiars[magiegebiet];
|
||||
assert(retval);
|
||||
|
@ -571,7 +568,7 @@ static int sp_summon_familiar(castorder * co)
|
|||
}
|
||||
rc = select_familiar(caster->_race, cast_level, caster->faction->magiegebiet);
|
||||
if (rc == NULL) {
|
||||
log_error("could not find suitable familiar for %s.\n", unitname(caster));
|
||||
log_error("could not find suitable familiar for %s.\n", caster->faction->race->_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4554,13 +4551,13 @@ int sp_illusionary_shapeshift(castorder * co)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == change_race(u, 3 + (int)power, NULL, rc)) {
|
||||
ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order,
|
||||
"sp_shapeshift_fail", "target race", u, rc));
|
||||
return 0;
|
||||
}
|
||||
add_trigger(&u->attribs, "timer", trigger_timeout((int)power + 3,
|
||||
trigger_changerace(u, NULL, irace)));
|
||||
u->irace = rc;
|
||||
|
||||
ADDMSG(&mage->faction->msgs, msg_message("shapeshift_effect",
|
||||
"mage target race", mage, u, rc));
|
||||
|
||||
return cast_level;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/curse.h>
|
||||
#include <kernel/event.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/order.h>
|
||||
#include <kernel/plane.h>
|
||||
|
@ -20,9 +19,6 @@
|
|||
|
||||
#include <attributes/attributes.h>
|
||||
|
||||
#include <triggers/changerace.h>
|
||||
#include <triggers/timeout.h>
|
||||
|
||||
#include <CuTest.h>
|
||||
#include <tests.h>
|
||||
|
||||
|
@ -284,58 +280,6 @@ static void test_watch_region(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_change_race(CuTest *tc) {
|
||||
unit *u;
|
||||
race *rctoad, *rcsmurf;
|
||||
trigger **tp, *tr;
|
||||
timeout_data *td;
|
||||
changerace_data *crd;
|
||||
|
||||
test_setup();
|
||||
rctoad = test_create_race("toad");
|
||||
rcsmurf = test_create_race("smurf");
|
||||
u = test_create_unit(test_create_faction(), test_create_plain(0, 0));
|
||||
CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)u->_race);
|
||||
CuAssertPtrNotNull(tc, tr = change_race(u, 2, rctoad, NULL));
|
||||
CuAssertPtrEquals(tc, (void *)rctoad, (void *)u->_race);
|
||||
CuAssertPtrEquals(tc, NULL, (void *)u->irace);
|
||||
CuAssertPtrEquals(tc, &tt_timeout, tr->type);
|
||||
CuAssertPtrNotNull(tc, u->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, u->attribs->next);
|
||||
tp = get_triggers(u->attribs, "timer");
|
||||
CuAssertPtrNotNull(tc, tp);
|
||||
CuAssertPtrEquals(tc, tr, *tp);
|
||||
CuAssertPtrEquals(tc, NULL, tr->next);
|
||||
td = (timeout_data *)tr->data.v;
|
||||
CuAssertPtrNotNull(tc, td);
|
||||
CuAssertIntEquals(tc, 2, td->timer);
|
||||
CuAssertPtrNotNull(tc, td->triggers);
|
||||
CuAssertPtrEquals(tc, &tt_changerace, td->triggers->type);
|
||||
CuAssertPtrEquals(tc, NULL, td->triggers->next);
|
||||
crd = (changerace_data *)td->triggers->data.v;
|
||||
CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)crd->race);
|
||||
CuAssertPtrEquals(tc, NULL, (void *)crd->irace);
|
||||
|
||||
/* change race, but do not add a second change_race trigger */
|
||||
CuAssertPtrEquals(tc, tr, change_race(u, 2, rcsmurf, NULL));
|
||||
CuAssertPtrNotNull(tc, u->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, u->attribs->next);
|
||||
CuAssertPtrEquals(tc, NULL, tr->next);
|
||||
CuAssertPtrEquals(tc, (void *)rcsmurf, (void *)u->_race);
|
||||
CuAssertPtrEquals(tc, NULL, (void *)u->irace);
|
||||
td = (timeout_data *)tr->data.v;
|
||||
CuAssertPtrNotNull(tc, td);
|
||||
CuAssertIntEquals(tc, 2, td->timer);
|
||||
CuAssertPtrNotNull(tc, td->triggers);
|
||||
CuAssertPtrEquals(tc, &tt_changerace, td->triggers->type);
|
||||
CuAssertPtrEquals(tc, NULL, td->triggers->next);
|
||||
crd = (changerace_data *)td->triggers->data.v;
|
||||
CuAssertPtrEquals(tc, (void *)u->faction->race, (void *)crd->race);
|
||||
CuAssertPtrEquals(tc, NULL, (void *)crd->irace);
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_spells_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -345,6 +289,5 @@ CuSuite *get_spells_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_good_dreams);
|
||||
SUITE_ADD_TEST(suite, test_bad_dreams);
|
||||
SUITE_ADD_TEST(suite, test_dreams);
|
||||
SUITE_ADD_TEST(suite, test_change_race);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1184,7 +1184,7 @@ int sp_appeasement(struct castorder * co)
|
|||
|
||||
/* Fliehende Einheiten verlassen auf jeden Fall Gebaeude und Schiffe. */
|
||||
if (!(r->terrain->flags & SEA_REGION)) {
|
||||
(void)leave(mage, false);
|
||||
leave(mage, false);
|
||||
}
|
||||
/* und bewachen nicht */
|
||||
setguard(mage, false);
|
||||
|
|
|
@ -119,7 +119,7 @@ int spy_cmd(unit * u, struct order *ord)
|
|||
|
||||
if (!target) {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, u->thisorder, "feedback_unit_not_found", NULL));
|
||||
msg_feedback(u, u->thisorder, "feedback_unit_not_found", ""));
|
||||
return 0;
|
||||
}
|
||||
if (effskill(u, SK_SPY, NULL) < 1) {
|
||||
|
|
|
@ -86,7 +86,7 @@ int update_nmrs(void)
|
|||
if (f->age<=1) {
|
||||
++newplayers;
|
||||
}
|
||||
else if (!fval(f, FFL_NOIDLEOUT | FFL_CURSED)) {
|
||||
else if (!fval(f, FFL_NOIDLEOUT|FFL_CURSED)) {
|
||||
int nmr = turn - f->lastorders;
|
||||
if (timeout>0) {
|
||||
if (nmr < 0 || nmr > timeout) {
|
||||
|
|
|
@ -74,7 +74,7 @@ void travelthru_add(region * r, unit * u)
|
|||
|
||||
bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u) {
|
||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||
return cansee(f, r, u, 0);
|
||||
return cansee_durchgezogen(f, r, u, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -86,10 +86,8 @@ trigger_type tt_changefaction = {
|
|||
trigger *trigger_changefaction(unit * u, struct faction * f)
|
||||
{
|
||||
trigger *t = t_new(&tt_changefaction);
|
||||
if (t) {
|
||||
changefaction_data *td = (changefaction_data *)t->data.v;
|
||||
td->unit = u;
|
||||
td->faction = f;
|
||||
}
|
||||
changefaction_data *td = (changefaction_data *)t->data.v;
|
||||
td->unit = u;
|
||||
td->faction = f;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <platform.h>
|
||||
#include "changerace.h"
|
||||
#include "timeout.h"
|
||||
|
||||
/* kernel includes */
|
||||
#include <kernel/unit.h>
|
||||
|
@ -27,6 +26,12 @@
|
|||
** restore a mage that was turned into a toad
|
||||
**/
|
||||
|
||||
typedef struct changerace_data {
|
||||
struct unit *u;
|
||||
const struct race *race;
|
||||
const struct race *irace;
|
||||
} changerace_data;
|
||||
|
||||
static void changerace_init(trigger * t)
|
||||
{
|
||||
t->data.v = calloc(1, sizeof(changerace_data));
|
||||
|
@ -85,35 +90,10 @@ trigger_type tt_changerace = {
|
|||
trigger *trigger_changerace(unit * u, const race * prace, const race * irace)
|
||||
{
|
||||
trigger *t = t_new(&tt_changerace);
|
||||
if (t) {
|
||||
changerace_data *td = (changerace_data *)t->data.v;
|
||||
changerace_data *td = (changerace_data *)t->data.v;
|
||||
|
||||
td->u = u;
|
||||
td->race = prace;
|
||||
td->irace = irace;
|
||||
}
|
||||
td->u = u;
|
||||
td->race = prace;
|
||||
td->irace = irace;
|
||||
return t;
|
||||
}
|
||||
|
||||
extern struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace) {
|
||||
trigger **texists = get_triggers(u->attribs, "timer");
|
||||
trigger *tr = NULL;
|
||||
|
||||
if (texists) {
|
||||
tr = *texists;
|
||||
}
|
||||
else {
|
||||
trigger *trestore = trigger_changerace(u, u_race(u), u->irace);
|
||||
if (trestore) {
|
||||
tr = trigger_timeout(duration, trestore);
|
||||
add_trigger(&u->attribs, "timer", tr);
|
||||
}
|
||||
}
|
||||
if (tr) {
|
||||
u->irace = irace;
|
||||
if (urace) {
|
||||
u_setrace(u, urace);
|
||||
}
|
||||
}
|
||||
return tr;
|
||||
}
|
||||
|
|
|
@ -10,15 +10,11 @@ extern "C" {
|
|||
struct unit;
|
||||
struct race;
|
||||
|
||||
typedef struct changerace_data {
|
||||
struct unit *u;
|
||||
const struct race *race;
|
||||
const struct race *irace;
|
||||
} changerace_data;
|
||||
|
||||
extern struct trigger_type tt_changerace;
|
||||
|
||||
extern struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace);
|
||||
extern struct trigger *trigger_changerace(struct unit *u,
|
||||
const struct race *urace, const struct race *irace);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -71,8 +71,6 @@ trigger_type tt_clonedied = {
|
|||
trigger *trigger_clonedied(unit * u)
|
||||
{
|
||||
trigger *t = t_new(&tt_clonedied);
|
||||
if (t) {
|
||||
t->data.v = (void *)u;
|
||||
}
|
||||
t->data.v = (void *)u;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -115,15 +115,13 @@ trigger *trigger_createcurse(struct unit * mage, struct unit * target,
|
|||
const curse_type * ct, double vigour, int duration, double effect, int men)
|
||||
{
|
||||
trigger *t = t_new(&tt_createcurse);
|
||||
if (t) {
|
||||
createcurse_data *td = (createcurse_data *)t->data.v;
|
||||
td->mage = mage;
|
||||
td->target = target;
|
||||
td->type = ct;
|
||||
td->vigour = vigour;
|
||||
td->duration = duration;
|
||||
td->effect = effect;
|
||||
td->men = men;
|
||||
}
|
||||
createcurse_data *td = (createcurse_data *)t->data.v;
|
||||
td->mage = mage;
|
||||
td->target = target;
|
||||
td->type = ct;
|
||||
td->vigour = vigour;
|
||||
td->duration = duration;
|
||||
td->effect = effect;
|
||||
td->men = men;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -103,12 +103,10 @@ trigger *trigger_createunit(region * r, struct faction * f,
|
|||
const struct race * rc, int number)
|
||||
{
|
||||
trigger *t = t_new(&tt_createunit);
|
||||
if (t) {
|
||||
createunit_data *td = (createunit_data *)t->data.v;
|
||||
td->r = r;
|
||||
td->f = f;
|
||||
td->race = rc;
|
||||
td->number = number;
|
||||
}
|
||||
createunit_data *td = (createunit_data *)t->data.v;
|
||||
td->r = r;
|
||||
td->f = f;
|
||||
td->race = rc;
|
||||
td->number = number;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -96,11 +96,9 @@ trigger_type tt_giveitem = {
|
|||
trigger *trigger_giveitem(unit * u, const item_type * itype, int number)
|
||||
{
|
||||
trigger *t = t_new(&tt_giveitem);
|
||||
if (t) {
|
||||
giveitem_data *td = (giveitem_data *)t->data.v;
|
||||
td->number = number;
|
||||
td->u = u;
|
||||
td->itype = itype;
|
||||
}
|
||||
giveitem_data *td = (giveitem_data *)t->data.v;
|
||||
td->number = number;
|
||||
td->u = u;
|
||||
td->itype = itype;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -61,8 +61,6 @@ trigger_type tt_killunit = {
|
|||
trigger *trigger_killunit(unit * u)
|
||||
{
|
||||
trigger *t = t_new(&tt_killunit);
|
||||
if (t) {
|
||||
t->data.v = (void *)u;
|
||||
}
|
||||
t->data.v = (void *)u;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -130,8 +130,6 @@ trigger_type tt_shock = {
|
|||
trigger *trigger_shock(unit * u)
|
||||
{
|
||||
trigger *t = t_new(&tt_shock);
|
||||
if (t) {
|
||||
t->data.v = (void *)u;
|
||||
}
|
||||
t->data.v = (void *)u;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
** timeout
|
||||
**/
|
||||
|
||||
typedef struct timeout_data {
|
||||
trigger *triggers;
|
||||
int timer;
|
||||
variant trigger_data;
|
||||
} timeout_data;
|
||||
|
||||
static void timeout_init(trigger * t)
|
||||
{
|
||||
t->data.v = calloc(1, sizeof(timeout_data));
|
||||
|
@ -79,10 +85,8 @@ trigger_type tt_timeout = {
|
|||
trigger *trigger_timeout(int time, trigger * callbacks)
|
||||
{
|
||||
trigger *t = t_new(&tt_timeout);
|
||||
if (t) {
|
||||
timeout_data *td = (timeout_data *)t->data.v;
|
||||
td->triggers = callbacks;
|
||||
td->timer = time;
|
||||
}
|
||||
timeout_data *td = (timeout_data *)t->data.v;
|
||||
td->triggers = callbacks;
|
||||
td->timer = time;
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,6 @@ extern "C" {
|
|||
struct trigger_type;
|
||||
struct trigger;
|
||||
|
||||
typedef struct timeout_data {
|
||||
struct trigger *triggers;
|
||||
int timer;
|
||||
} timeout_data;
|
||||
|
||||
extern struct trigger_type tt_timeout;
|
||||
|
||||
extern struct trigger *trigger_timeout(int time, struct trigger *callbacks);
|
||||
|
|
|
@ -156,8 +156,7 @@ const char *keywords[MAXKEYWORDS] = {
|
|||
"promote",
|
||||
"pay",
|
||||
"loot",
|
||||
"expel",
|
||||
"autostudy",
|
||||
"locale"
|
||||
"locale",
|
||||
};
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ extern "C"
|
|||
K_PROMOTION,
|
||||
K_PAY,
|
||||
K_LOOT,
|
||||
K_EXPEL,
|
||||
K_AUTOSTUDY,
|
||||
K_LOCALE,
|
||||
MAXKEYWORDS,
|
||||
|
|
|
@ -24,9 +24,7 @@ typedef struct parse_state {
|
|||
|
||||
static parse_state *states;
|
||||
|
||||
#define TRIMMED(wc) (iswspace(wc) || iswcntrl(wc) || (wc) == 160 || (wc) == 8199 || (wc) == 8239)
|
||||
|
||||
int ltrim(const char **str_p)
|
||||
static int eatwhitespace_c(const char **str_p)
|
||||
{
|
||||
int ret = 0;
|
||||
wint_t wc;
|
||||
|
@ -34,10 +32,11 @@ int ltrim(const char **str_p)
|
|||
const char *str = *str_p;
|
||||
|
||||
/* skip over potential whitespace */
|
||||
while (*str) {
|
||||
wc = *(unsigned char *)str;
|
||||
if (~wc & 0x80) {
|
||||
if (!TRIMMED(wc)) break;
|
||||
for (;;) {
|
||||
unsigned char utf8_character = (unsigned char)*str;
|
||||
if (~utf8_character & 0x80) {
|
||||
if (!iswspace(utf8_character))
|
||||
break;
|
||||
++str;
|
||||
}
|
||||
else {
|
||||
|
@ -46,7 +45,8 @@ int ltrim(const char **str_p)
|
|||
log_warning("illegal character sequence in UTF8 string: %s\n", str);
|
||||
break;
|
||||
}
|
||||
if (!TRIMMED(wc)) break;
|
||||
if (!iswspace(wc))
|
||||
break;
|
||||
str += len;
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ void parser_popstate(void)
|
|||
bool parser_end(void)
|
||||
{
|
||||
if (states->current_token) {
|
||||
ltrim(&states->current_token);
|
||||
eatwhitespace_c(&states->current_token);
|
||||
return *states->current_token == 0;
|
||||
}
|
||||
return true;
|
||||
|
@ -103,7 +103,7 @@ bool parser_end(void)
|
|||
void skip_token(void)
|
||||
{
|
||||
char quotechar = 0;
|
||||
ltrim(&states->current_token);
|
||||
eatwhitespace_c(&states->current_token);
|
||||
|
||||
while (*states->current_token) {
|
||||
wint_t wc;
|
||||
|
@ -152,7 +152,7 @@ char *parse_token(const char **str, char *lbuf, size_t buflen)
|
|||
if (!ctoken) {
|
||||
return 0;
|
||||
}
|
||||
ltrim(&ctoken);
|
||||
eatwhitespace_c(&ctoken);
|
||||
if (!*ctoken) {
|
||||
if (buflen > 0) {
|
||||
*cursor = 0;
|
||||
|
@ -195,19 +195,18 @@ char *parse_token(const char **str, char *lbuf, size_t buflen)
|
|||
}
|
||||
else if (utf8_character == '"' || utf8_character == '\'') {
|
||||
if (utf8_character == quotechar) {
|
||||
quotechar = 0;
|
||||
++ctoken;
|
||||
break;
|
||||
}
|
||||
else if (quotechar == 0 && cstart == ctoken) {
|
||||
quotechar = utf8_character;
|
||||
++ctoken;
|
||||
}
|
||||
else {
|
||||
if (cursor - buflen < lbuf - len) {
|
||||
*cursor++ = *ctoken;
|
||||
*cursor++ = *ctoken++;
|
||||
}
|
||||
}
|
||||
++ctoken;
|
||||
}
|
||||
else if (utf8_character == SPACE_REPLACEMENT) {
|
||||
if (cursor - buflen < lbuf - len) {
|
||||
|
|
|
@ -22,7 +22,6 @@ extern "C" {
|
|||
int getint(void);
|
||||
int getid(void);
|
||||
unsigned int atoip(const char *s);
|
||||
int ltrim(const char **str_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -92,14 +92,8 @@ static void test_parse_token_limit_utf8(CuTest *tc) {
|
|||
char lbuf[8];
|
||||
const char *tok;
|
||||
const char *orig = "a\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f"; /* auml ouml uuml szlig, 8 bytes long */
|
||||
const char *str;
|
||||
const char *wspace = " \x07\xc2\xa0\t.okay";
|
||||
const char *str = orig+1;
|
||||
|
||||
str = wspace;
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertStrEquals(tc, tok, ".okay");
|
||||
|
||||
str = orig + 1;
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str);
|
||||
CuAssertStrEquals(tc, tok, "\xc3\xa4\xc3\xb6\xc3\xbc"); /* just three letters fit, 6 bytes long */
|
||||
|
|
|
@ -21,11 +21,11 @@ static void test_transliterate(CuTest * tc)
|
|||
CuAssertStrEquals(tc, "aeoeuess", transliterate(buffer, sizeof(buffer), "\xc3\x84\xc3\x96\xc3\x9c\xe1\xba\x9e"));
|
||||
|
||||
/* handle buffer that is too small */
|
||||
CuAssertStrEquals(tc, NULL, transliterate(buffer, 1, "herpderp"));
|
||||
CuAssertStrEquals(tc, 0, transliterate(buffer, 1, "herpderp"));
|
||||
CuAssertStrEquals(tc, "", buffer);
|
||||
CuAssertStrEquals(tc, NULL, transliterate(buffer, 3, "herpderp"));
|
||||
CuAssertStrEquals(tc, 0, transliterate(buffer, 3, "herpderp"));
|
||||
CuAssertStrEquals(tc, "he", buffer);
|
||||
CuAssertStrEquals(tc, NULL, transliterate(buffer, 3, "h\xc3\xa4rpd\xc3\xa4rp"));
|
||||
CuAssertStrEquals(tc, 0, transliterate(buffer, 3, "h\xc3\xa4rpd\xc3\xa4rp"));
|
||||
CuAssertStrEquals(tc, "h?", buffer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue