added shroud. Tweaked some units, added new scenario
This commit is contained in:
parent
2be9acb023
commit
afdb6002e6
48 changed files with 925 additions and 166 deletions
|
@ -7,6 +7,13 @@
|
|||
[units]
|
||||
{units}
|
||||
|
||||
[trait]
|
||||
name=loyal
|
||||
[effect]
|
||||
apply_to=loyal
|
||||
[/effect]
|
||||
[/trait]
|
||||
|
||||
[trait]
|
||||
name=strong
|
||||
[effect]
|
||||
|
@ -38,7 +45,7 @@
|
|||
name=intelligent
|
||||
[effect]
|
||||
apply_to=max_experience
|
||||
increase=-7
|
||||
increase=-6
|
||||
[/effect]
|
||||
[/trait]
|
||||
|
||||
|
@ -64,6 +71,8 @@
|
|||
mountains=3
|
||||
village=1
|
||||
castle=1
|
||||
cave=2
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -76,6 +85,8 @@
|
|||
mountains=0.4
|
||||
village=0.4
|
||||
castle=0.4
|
||||
cave=0.6
|
||||
cavewall=0.1
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -100,6 +111,8 @@
|
|||
mountains=2
|
||||
village=1
|
||||
castle=1
|
||||
cave=1
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -112,6 +125,7 @@
|
|||
mountains=0.4
|
||||
village=0.6
|
||||
castle=0.6
|
||||
cave=0.6
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -136,6 +150,8 @@
|
|||
mountains=3
|
||||
village=1
|
||||
castle=1
|
||||
cave=1
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -148,6 +164,7 @@
|
|||
mountains=0.3
|
||||
village=0.3
|
||||
castle=0.3
|
||||
cave=0.5
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -173,6 +190,8 @@
|
|||
mountains=100
|
||||
village=1
|
||||
castle=1
|
||||
cave=4
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -185,6 +204,7 @@
|
|||
mountains=0.8
|
||||
village=0.6
|
||||
castle=0.6
|
||||
cave=0.8
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -209,6 +229,8 @@
|
|||
mountains=4
|
||||
village=1
|
||||
castle=1
|
||||
cave=3
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -221,6 +243,7 @@
|
|||
mountains=0.4
|
||||
village=0.4
|
||||
castle=0.4
|
||||
cave=0.7
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -245,6 +268,8 @@
|
|||
mountains=1
|
||||
village=1
|
||||
castle=1
|
||||
cave=2
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -257,6 +282,7 @@
|
|||
mountains=0.7
|
||||
village=0.7
|
||||
castle=0.7
|
||||
cave=0.7
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -281,6 +307,8 @@
|
|||
mountains=100
|
||||
village=1
|
||||
castle=1
|
||||
cave=3
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -293,6 +321,7 @@
|
|||
mountains=0.8
|
||||
village=0.6
|
||||
castle=0.6
|
||||
cave=0.8
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -317,6 +346,8 @@
|
|||
mountains=1
|
||||
village=1
|
||||
castle=1
|
||||
cave=1
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -329,6 +360,7 @@
|
|||
mountains=0.3
|
||||
village=0.6
|
||||
castle=0.6
|
||||
cave=0.5
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -341,42 +373,6 @@
|
|||
[/resistance]
|
||||
[/movetype]
|
||||
|
||||
[movetype]
|
||||
name=largemountain
|
||||
[movement costs]
|
||||
deep water=100
|
||||
shallow water=100
|
||||
grassland=1
|
||||
sand=2
|
||||
forest=3
|
||||
hills=1
|
||||
mountains=1
|
||||
village=1
|
||||
castle=1
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
deep water=0.8
|
||||
shallow water=0.7
|
||||
grassland=0.7
|
||||
sand=0.7
|
||||
forest=0.7
|
||||
hills=0.6
|
||||
mountains=0.4
|
||||
village=0.6
|
||||
castle=0.6
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
blade=0.8
|
||||
pierce=1.0
|
||||
impact=1.0
|
||||
fire=1.0
|
||||
cold=1.0
|
||||
holy=0.8
|
||||
[/resistance]
|
||||
[/movetype]
|
||||
|
||||
[movetype]
|
||||
name=undeadfoot
|
||||
[movement costs]
|
||||
|
@ -389,6 +385,8 @@
|
|||
mountains=100
|
||||
village=1
|
||||
castle=1
|
||||
cave=2
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -401,6 +399,7 @@
|
|||
mountains=0.4
|
||||
village=0.4
|
||||
castle=0.4
|
||||
cave=0.6
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
@ -425,6 +424,8 @@
|
|||
mountains=1
|
||||
village=1
|
||||
castle=1
|
||||
cave=1
|
||||
cavewall=100
|
||||
[/movement costs]
|
||||
|
||||
[defense]
|
||||
|
@ -437,6 +438,7 @@
|
|||
mountains=0.5
|
||||
village=0.5
|
||||
castle=0.5
|
||||
cave=0.6
|
||||
[/defense]
|
||||
|
||||
[resistance]
|
||||
|
|
31
data/maps/map12
Normal file
31
data/maps/map12
Normal file
|
@ -0,0 +1,31 @@
|
|||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
|
||||
uuuuuuuuuuuuuuuWWWWuWuuuuuuuuuuuuuuuuWuuu
|
||||
uuuuuuuuuuuuuWWuuWWWWWuuuuuuuuuuuuuWWWuuu
|
||||
uuuuuuuuuuuuuWuCCuuuuuWuuuuuuuuuuuuWuuWWu
|
||||
uuuuuuuuuuuuWuCCCCCCCuWuuuuuuuuuuuWuuuuWu
|
||||
uuuuuuuuuuuuWuuCCCCCCuWWuuuuuuuuWWuWuuuuW
|
||||
uuuuuuuuuuuuWuuCCCCCuCWWuuuuuuuWuWWuuuuuW
|
||||
uuuuuuuuuuuuWWuCCCCCuCuWWWuuuuuWuuuuuuuuW
|
||||
CCuuuuuuuuuuWuCCCC3CCuuuWWWWWuuWuuuuuuuuW
|
||||
u2CuuuuuuuuuuWuCCCCCCuuuuuuWWWWWuuuuWuuuW
|
||||
uCuuuuuuuuuuuWuCCCCCuuuuuuuuuWWWWuuWuWuuW
|
||||
uuuuuuuuuuuuuWuCCCCCcCuuuuuuuuWuWWWWuWuuW
|
||||
uuuuuuuuuuuuuWuCCCCCcWWWuuuuuuuuuWWWWWWuW
|
||||
uuuuuuuuuuuuuuWCCCCCccWWWuuuuuuuuuWuWWWWW
|
||||
uuuuuuuuuuuuuuWuuuucWWuuWWWuuuuuuuuuuuuWW
|
||||
uuuuuuuuuuuuuuuWWuuWWuuuuuWWuuuuuuuuuuuuW
|
||||
uuuuuuuuuuuuuuuuWWWuuuuuuuWWuuuuuuuuuuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuWWuuuuuuuuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuWWWWWWWuuuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuWWWWWWWWuuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuWWuuuuWuuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWWuuuW
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWuuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWuuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWuuu
|
||||
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuWu1
|
|
@ -15,7 +15,7 @@
|
|||
[/side]
|
||||
|
||||
[side]
|
||||
type=Orcish Grunt
|
||||
type=Orcish Crossbow
|
||||
description=Urug-Telfar
|
||||
side=2
|
||||
canrecruit=1
|
||||
|
|
|
@ -54,6 +54,7 @@ Defeat:
|
|||
side=2
|
||||
canrecruit=1
|
||||
recruit=Vampire Bat,Naga
|
||||
recruitment_pattern=scout,fighter
|
||||
#ifdef EASY
|
||||
gold=100
|
||||
#endif
|
||||
|
|
|
@ -74,8 +74,8 @@ Defeat:
|
|||
description=Knafa-Telfar
|
||||
side=2
|
||||
canrecruit=1
|
||||
recruit=Orcish Warrior,Wolf Rider,Orcish Crossbow,Orcish Assasin,Troll
|
||||
gold=250
|
||||
recruit=Orcish Warrior,Wolf Rider,Orcish Crossbow,Orcish Assasin,Troll Warrior
|
||||
gold=450
|
||||
enemy=1
|
||||
[/side]
|
||||
|
||||
|
@ -84,8 +84,8 @@ Defeat:
|
|||
description=Urug-Tan
|
||||
side=3
|
||||
canrecruit=1
|
||||
recruit=Orcish Grunt,Goblin Knight,Orcish Crossbow,Orcish Assasin,Troll
|
||||
gold=300
|
||||
recruit=Orcish Grunt,Goblin Knight,Orcish Crossbow,Orcish Assasin,Troll Warrior
|
||||
gold=500
|
||||
enemy=1
|
||||
[/side]
|
||||
|
||||
|
@ -96,7 +96,7 @@ Defeat:
|
|||
side=4
|
||||
canrecruit=1
|
||||
recruit=Orcish Warrior,Wolf Rider,Orcish Crossbow,Troll Warrior,Orcish Slayer
|
||||
gold=300
|
||||
gold=500
|
||||
enemy=1
|
||||
[/side]
|
||||
|
||||
|
|
351
data/scenarios/scenario12.cfg
Normal file
351
data/scenarios/scenario12.cfg
Normal file
|
@ -0,0 +1,351 @@
|
|||
[scenario]
|
||||
name="Scenario 11B: Plunging into the Darkness"
|
||||
map=map12
|
||||
turns=16
|
||||
|
||||
id=scenario12
|
||||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=187
|
||||
y=187
|
||||
[/dot]
|
||||
[/bigmap]
|
||||
|
||||
objectives="
|
||||
Victory:
|
||||
@Find the Dwarves
|
||||
Defeat
|
||||
#Death of Konrad
|
||||
#Death of Delfador
|
||||
#Death of Kalenz
|
||||
#Death of Li'sar"
|
||||
|
||||
[side]
|
||||
type=Commander
|
||||
description=Konrad
|
||||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
enemy=2
|
||||
shroud=yes
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
type=Orcish Warlord
|
||||
side=2
|
||||
canrecruit=1
|
||||
recruit=Orcish Warrior
|
||||
gold=0
|
||||
enemy=1
|
||||
aggression=1.0
|
||||
[unit]
|
||||
type=Blood Bat
|
||||
x=17
|
||||
y=36
|
||||
side=2
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Blood Bat
|
||||
x=21
|
||||
y=31
|
||||
side=2
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Blood Bat
|
||||
x=15
|
||||
y=32
|
||||
side=2
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Blood Bat
|
||||
x=15
|
||||
y=25
|
||||
side=2
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
type=Giant Spider
|
||||
x=16
|
||||
y=40
|
||||
side=2
|
||||
[/unit]
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
description=Geldar
|
||||
type=Dwarvish Lord
|
||||
side=3
|
||||
canrecruit=1
|
||||
recruit=Dwarvish Fighter
|
||||
gold=0
|
||||
enemy=4 #dummy non-existent side
|
||||
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=15
|
||||
y=22
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=10
|
||||
y=22
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=13
|
||||
y=20
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=11
|
||||
y=20
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=13
|
||||
y=19
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=11
|
||||
y=19
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=8
|
||||
y=20
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=17
|
||||
y=19
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=15
|
||||
y=16
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[unit]
|
||||
type=Dwarvish Fighter
|
||||
x=9
|
||||
y=16
|
||||
side=3
|
||||
ai_special=guardian
|
||||
[/unit]
|
||||
[/side]
|
||||
|
||||
[event]
|
||||
name=start
|
||||
[recall]
|
||||
description=Delfador
|
||||
[/recall]
|
||||
[recall]
|
||||
description=Kalenz
|
||||
[/recall]
|
||||
[recall]
|
||||
description=Li'sar
|
||||
[/recall]
|
||||
[message]
|
||||
id=msg12_1
|
||||
description=Konrad
|
||||
message="It's so dark in here! I can hardly see!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_2
|
||||
description=Delfador
|
||||
message="It is dark indeed. We shall have to light torches, and tread slowly and warily. Hopefully there are still Dwarves down here who can aid us!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_3
|
||||
description=Kalenz
|
||||
message="Indeed. Us Elves are not well-skilled in these dark pits."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_4
|
||||
description=Li'sar
|
||||
message="This isn't so bad. When I grew up in the castle, I often used to explore the secret passages."
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=moveto
|
||||
[filter]
|
||||
side=1
|
||||
y=10-21
|
||||
x=1-100
|
||||
[/filter]
|
||||
[message]
|
||||
id=msg12_5
|
||||
description=Geldar
|
||||
message="Who are these that approach? Surface-dwellers! On guard men!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_6
|
||||
description=Delfador
|
||||
message="We come in peace, friends. We come in peace!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_7
|
||||
description=Geldar
|
||||
message="Oh do you? I see you are even accompanied by Elves. Can us Dwarves not live in peace without the treacherous Elves coming to bother us?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_8
|
||||
description=Kalenz
|
||||
message="Why such harsh words, Dwarf? Elves have never done you any harm."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_9
|
||||
description=Geldar
|
||||
message="Never done us any harm? Why I was there myself, when the Elves did not come to honor our alliance. Many Dwarves were slaughtered, and you cowardly Elves did nothing to help!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_10
|
||||
description=Kalenz
|
||||
message="You go too far! I am Kalenz, a mighty Elvish lord! How dare such as you, snivelling around in his tunnel, dare to call me a coward?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_11
|
||||
description=Delfador
|
||||
message="Peace friends! Peace! The evil Orcs roam the lands above us, must we also fight among ourselves?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_12
|
||||
description=Geldar
|
||||
message="Very well! Who are you? Explain your presence here then, human. Why have you risked life and limb to come to Knalga, the home of the Dwarves?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_13
|
||||
description=Konrad
|
||||
message="Well, we....we..."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_14
|
||||
description=Delfador
|
||||
message="We have come so that an heir may claim his inheritance. That a king may claim his throne. We seek the Sceptre of Fire."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_15
|
||||
description=Geldar
|
||||
message="The Sceptre of Fire? Are you out of your mind? Surely you speak but only in jest!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_16
|
||||
description=Delfador
|
||||
message="We jest not, friend. We seek the Sceptre of Fire. We seek the help of the Dwarves in finding it. Choose to help us not, if you so wish. We will find it, whether you help us or not."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_17
|
||||
description=Geldar
|
||||
message="Your speech is like that of a fool. No-one even knows if the Sceptre of Fire exists. Who is this heir, this king that you speak of, anyhow?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_18
|
||||
description=Konrad
|
||||
message="I am, Sir."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_19
|
||||
description=Geldar
|
||||
message="You, haha, this boy that stands before me is the king of Wesnoth? Haha! I haven't had such a laugh in a long time. And whom are you, old man?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_20
|
||||
description=Delfador
|
||||
message="I am Delfador. Delfador the Great, Arch Mage to King Garard, and Protector of his heir."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_21
|
||||
description=Geldar
|
||||
message="You....you are Delfador? I have seen Delfador when I was but a young Dwarf, and I will tell you old man, you are not Delfador. Men! Take these liars out of my sight. Delfador perished many years ago."
|
||||
[/message]
|
||||
[message]
|
||||
sound=lightning.wav
|
||||
id=msg12_22
|
||||
description=Delfador
|
||||
message="I am Delfador the Great! Any who dare oppose me shall perish!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_23
|
||||
description=Geldar
|
||||
message="You...you really are Delfador! But we had news that you were dead, years ago!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_24
|
||||
description=Delfador
|
||||
message="They thought I was dead. They hoped I was dead. Yet still, still I live."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_25
|
||||
description=Geldar
|
||||
message="And you really think you can find, the Sceptre of Fire?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_26
|
||||
description=Delfador
|
||||
message="Yes we do. If you help us, friend, all the treasures of Knalga that we find are yours. We want only the Sceptre. It will be dangerous. Make no mistake about that: Dwarves will be killed, perhaps many Dwarves. But surely it is better than hiding from the Orcs like worms."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_27
|
||||
description=Geldar
|
||||
message="You are right, friend. I will put my best men at your disposal. We know not where the Sceptre is though. Legend says it is hidden in the northern tunnels."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg12_28
|
||||
description=Delfador
|
||||
message="Then to the northern tunnels we shall go!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
result=victory
|
||||
[/endlevel]
|
||||
[/event]
|
||||
|
||||
#a secret passage that only Li'sar can find
|
||||
[event]
|
||||
name=moveto
|
||||
[filter]
|
||||
x=17
|
||||
y=36
|
||||
type=Princess
|
||||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
message="Hmm...there seems to be a secret passage behind these rocks!"
|
||||
[/message]
|
||||
[terrain]
|
||||
x=16
|
||||
y=36
|
||||
letter=u
|
||||
[/terrain]
|
||||
|
||||
[/event]
|
||||
|
||||
{deaths.cfg}
|
||||
|
||||
[/scenario]
|
|
@ -96,3 +96,20 @@ red=100
|
|||
green=100
|
||||
blue=100
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=cavewall
|
||||
name=cavewall
|
||||
char=W
|
||||
red=50
|
||||
green=50
|
||||
blue=20
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=cave
|
||||
name=cave
|
||||
char=u
|
||||
red=120
|
||||
green=120
|
||||
[/terrain]
|
||||
|
|
|
@ -17,8 +17,8 @@ language="English"
|
|||
[/hotkey]
|
||||
[hotkey]
|
||||
command=recall
|
||||
key=c
|
||||
ctrl=yes
|
||||
key=r
|
||||
alt=yes
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=cycle
|
||||
|
@ -73,6 +73,11 @@ language="English"
|
|||
key=s
|
||||
ctrl=yes
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=endturn
|
||||
key=e
|
||||
alt=yes
|
||||
[/hotkey]
|
||||
|
||||
game_title="The Battle for Wesnoth"
|
||||
version="Version"
|
||||
|
@ -143,12 +148,13 @@ early_finish_bonus="Early finish bonus"
|
|||
per_turn="per turn"
|
||||
turns_finished_early="Turns finished early"
|
||||
retained_gold="Retained Gold"
|
||||
fifty_percent="50% of gold is retained for the next scenario"
|
||||
fifty_percent="80% of gold is retained for the next scenario"
|
||||
bonus="Bonus"
|
||||
gold="Gold"
|
||||
turn="Turn"
|
||||
villages="Villages"
|
||||
units="Units"
|
||||
upkeep="Upkeep"
|
||||
income="Income"
|
||||
|
||||
name="Name"
|
||||
|
@ -221,6 +227,7 @@ movement="Movement"
|
|||
defense="Defense"
|
||||
|
||||
attack_resistance="Resistance"
|
||||
unit_resistance_table="Unit resistance table"
|
||||
close_window="Close Window"
|
||||
|
||||
see_also="See Also..."
|
||||
|
@ -242,5 +249,7 @@ forest="Forest"
|
|||
bridge="Bridge"
|
||||
castle="Castle"
|
||||
keep="Keep"
|
||||
cave="Cave"
|
||||
cavewall="Cave Wall"
|
||||
|
||||
[/language]
|
||||
|
|
31
data/units/Cave_Spider.cfg
Normal file
31
data/units/Cave_Spider.cfg
Normal file
|
@ -0,0 +1,31 @@
|
|||
[unit]
|
||||
name=Giant Spider
|
||||
image=cavespider.png
|
||||
hitpoints=54
|
||||
movement_type=mountainfoot
|
||||
movement=6
|
||||
experience=500
|
||||
level=3
|
||||
alignment=chaotic
|
||||
advanceto=null
|
||||
cost=48
|
||||
usage=fighter
|
||||
unit_description="Giant spiders are said to roam the depths of Knalga, devouring many victims. They can bite at close range, poisoning their enemies, and attack with a web at long range, slowing their foes down."
|
||||
[attack]
|
||||
name=bite
|
||||
type=blade
|
||||
range=short
|
||||
damage=18
|
||||
number=2
|
||||
special=poison
|
||||
[/attack]
|
||||
|
||||
[attack]
|
||||
name=web
|
||||
type=impact
|
||||
range=long
|
||||
damage=8
|
||||
number=3
|
||||
special=slows
|
||||
[/attack]
|
||||
[/unit]
|
22
data/units/Dwarvish_Fighter.cfg
Normal file
22
data/units/Dwarvish_Fighter.cfg
Normal file
|
@ -0,0 +1,22 @@
|
|||
[unit]
|
||||
name=Dwarvish Fighter
|
||||
image=dwarf-fighter.png
|
||||
hitpoints=38
|
||||
movement_type=mountainfoot
|
||||
movement=4
|
||||
experience=42
|
||||
level=1
|
||||
alignment=neutral
|
||||
advanceto=Dwarvish Lord
|
||||
cost=15
|
||||
usage=fighter
|
||||
unit_description="The Dwarvish Fighters are excellent underground and in mountainous terrain. Skilled at close range combat, the sheer power of their battle axe makes them a feared opponent. Their power and endurance makes up for their slow speed."
|
||||
|
||||
[attack]
|
||||
name=battle axe
|
||||
type=blade
|
||||
range=short
|
||||
damage=8
|
||||
number=3
|
||||
[/attack]
|
||||
[/unit]
|
|
@ -8,7 +8,7 @@ experience=42
|
|||
level=1
|
||||
alignment=lawful
|
||||
advanceto=Elvish Ranger,Elvish Marksman
|
||||
cost=22
|
||||
cost=18
|
||||
usage=scout
|
||||
unit_description="Being trained from youth in archery, the Elvish Archer is skilled in long range combat. Being able to fire many arrows quickly and accurately, the Elvish Archer makes up a large portion of the Elvish military."
|
||||
[attack]
|
||||
|
|
|
@ -4,7 +4,7 @@ image=elvish-avenger.png
|
|||
hitpoints=60
|
||||
movement_type=woodland
|
||||
movement=6
|
||||
experience=80
|
||||
experience=500
|
||||
level=3
|
||||
alignment=lawful
|
||||
advanceto=null
|
||||
|
@ -23,7 +23,7 @@ unit_description="Extremely skillful and extremely quick, the Elvish Avenger is
|
|||
name=bow
|
||||
type=pierce
|
||||
range=long
|
||||
damage=12
|
||||
damage=11
|
||||
number=4
|
||||
[sound]
|
||||
time=-100
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[unit]
|
||||
name=Elvish Fighter
|
||||
image=elvish-fighter.png
|
||||
image_long=elvish-fighter-bow.png
|
||||
image_defensive=elvish-fighter-defend.png
|
||||
image_defensive_long=elvish-fighter-bow-defend.png
|
||||
hitpoints=32
|
||||
|
|
|
@ -23,7 +23,7 @@ unit_description="The Elvish Ranger is quick and powerful. Skilled in both short
|
|||
name=bow
|
||||
type=pierce
|
||||
range=long
|
||||
damage=8
|
||||
damage=7
|
||||
number=4
|
||||
[sound]
|
||||
time=-100
|
||||
|
|
|
@ -9,7 +9,7 @@ experience=32
|
|||
level=1
|
||||
alignment=neutral
|
||||
advanceto=Elvish Druid
|
||||
cost=27
|
||||
cost=21
|
||||
usage=healer
|
||||
unit_description="The Elvish Shaman focuses on less violent ways to hinder the enemy. Her entangling attack slows enemies down and reduces the number of times they may attack. She also possesses basic healing abilities."
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ experience=38
|
|||
level=1
|
||||
alignment=neutral
|
||||
advanceto=Knight,Elvish Outrider
|
||||
cost=28
|
||||
cost=23
|
||||
usage=fighter
|
||||
unit_description="Trained from childhood to ride, Horsemen are both fast and powerful at attacking. Charging at their enemies, their attacks do double damage, but also cause the horsemen to receive double damage when struck."
|
||||
[attack]
|
||||
|
|
|
@ -8,7 +8,7 @@ experience=45
|
|||
level=1
|
||||
alignment=neutral
|
||||
advanceto=White Mage,Red Mage
|
||||
cost=42
|
||||
cost=34
|
||||
usage=mixed fighter
|
||||
unit_description="The mage is weak and yet potent. Moving slowly, and weak defensively, the mage attacks with magical missiles, that always have a high chance of hitting their target.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ name=Princess
|
|||
image=human-princess.png
|
||||
hitpoints=48
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
movement=6
|
||||
experience=500
|
||||
level=3
|
||||
alignment=neutral
|
||||
|
@ -11,7 +11,7 @@ advanceto=null
|
|||
cost=110
|
||||
ability=leadership
|
||||
usage=fighter
|
||||
unit_description="A noble at birth, the princess has learned swordplay with the greatest generals, and battle tatics with the greatest sages, making her both a great combatant and leader. All the units of lower level around the princess will fight better due to her shining presence."
|
||||
unit_description="A noble at birth, the princess has learnt swordplay with the greatest generals, and battle tactics with the greatest sages, making her both a great combatant and leader. The units of lower level around the princess will fight better due to her presence. The princess is also nimble and dextrous, having skills like that of a thief."
|
||||
[attack]
|
||||
name=sword
|
||||
type=blade
|
||||
|
|
BIN
images/cavespider.png
Normal file
BIN
images/cavespider.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 819 B |
BIN
images/terrain/cave.png
Normal file
BIN
images/terrain/cave.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
images/terrain/cavewall.png
Normal file
BIN
images/terrain/cavewall.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
|
@ -47,7 +47,7 @@ private:
|
|||
|
||||
std::string recruit_unit(const gamemap& map, int side,
|
||||
std::map<gamemap::location,unit>& units, unit& new_unit,
|
||||
gamemap::location recruit_location, display* disp)
|
||||
gamemap::location recruit_location, display* disp, bool need_castle)
|
||||
{
|
||||
typedef std::map<gamemap::location,unit> units_map;
|
||||
|
||||
|
@ -75,7 +75,8 @@ std::string recruit_unit(const gamemap& map, int side,
|
|||
}
|
||||
|
||||
if(!map.on_board(recruit_location)) {
|
||||
recruit_location = find_vacant_tile(map,units,u->first,gamemap::CASTLE);
|
||||
recruit_location = find_vacant_tile(map,units,u->first,
|
||||
need_castle ? gamemap::CASTLE : 0);
|
||||
}
|
||||
|
||||
if(!map.on_board(recruit_location)) {
|
||||
|
@ -87,7 +88,8 @@ std::string recruit_unit(const gamemap& map, int side,
|
|||
units.insert(std::pair<gamemap::location,unit>(
|
||||
recruit_location,new_unit));
|
||||
|
||||
if(disp != NULL && !disp->turbo()) {
|
||||
if(disp != NULL && !disp->turbo() &&
|
||||
!disp->shrouded(recruit_location.x,recruit_location.y)) {
|
||||
disp->draw(true,true);
|
||||
|
||||
for(double alpha = 0.0; alpha <= 1.0; alpha += 0.1) {
|
||||
|
@ -328,9 +330,9 @@ void attack(display& gui, const gamemap& map,
|
|||
hits ? stats.damage_defender_takes : 0,
|
||||
a->second.attacks()[attack_with]);
|
||||
if(dies) {
|
||||
attackerxp = 10*d->second.type().level();
|
||||
attackerxp = 8*d->second.type().level();
|
||||
if(d->second.type().level() == 0)
|
||||
attackerxp = 5;
|
||||
attackerxp = 4;
|
||||
|
||||
defenderxp = 0;
|
||||
|
||||
|
@ -386,9 +388,9 @@ void attack(display& gui, const gamemap& map,
|
|||
d->second.attacks()[stats.defend_with]);
|
||||
|
||||
if(dies) {
|
||||
defenderxp = 10*a->second.type().level();
|
||||
defenderxp = 8*a->second.type().level();
|
||||
if(a->second.type().level() == 0)
|
||||
defenderxp = 5;
|
||||
defenderxp = 4;
|
||||
|
||||
attackerxp = 0;
|
||||
|
||||
|
@ -583,7 +585,8 @@ void calculate_healing(display& disp, const gamemap& map,
|
|||
|
||||
const gamemap::location& loc = h->first;
|
||||
|
||||
const bool show_healing = !disp.turbo() && !recorder.skipping();
|
||||
const bool show_healing = !disp.turbo() && !recorder.skipping() &&
|
||||
!disp.shrouded(loc.x,loc.y);
|
||||
|
||||
assert(units.count(loc) == 1);
|
||||
|
||||
|
@ -871,3 +874,53 @@ size_t move_unit(display* disp, const gamemap& map,
|
|||
|
||||
return steps.size();
|
||||
}
|
||||
|
||||
void clear_shroud_loc(const gamemap& map, team& tm,
|
||||
const gamemap::location& loc)
|
||||
{
|
||||
if(map.on_board(loc))
|
||||
tm.clear_shroud(loc.x,loc.y);
|
||||
|
||||
static gamemap::location adj[6];
|
||||
get_adjacent_tiles(loc,adj);
|
||||
for(int i = 0; i != 6; ++i) {
|
||||
if(map.on_board(adj[i])) {
|
||||
tm.clear_shroud(adj[i].x,adj[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_shroud_unit(const gamemap& map, const game_data& gamedata,
|
||||
const unit_map& units, const gamemap::location& loc,
|
||||
std::vector<team>& teams, int team)
|
||||
{
|
||||
paths p(map,gamedata,units,loc,teams,true,false);
|
||||
for(paths::routes_map::const_iterator i = p.routes.begin();
|
||||
i != p.routes.end(); ++i) {
|
||||
clear_shroud_loc(map,teams[team],i->first);
|
||||
}
|
||||
}
|
||||
|
||||
bool clear_shroud(display& disp, const gamemap& map, const game_data& gamedata,
|
||||
const unit_map& units, std::vector<team>& teams, int team)
|
||||
{
|
||||
if(teams[team].uses_shroud() == false)
|
||||
return false;
|
||||
|
||||
for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() == team+1) {
|
||||
|
||||
//we're not really going to mutate the unit, just temporarily
|
||||
//set its moves to maximum, but then switch them back
|
||||
unit& mutable_unit = const_cast<unit&>(i->second);
|
||||
const int old_moves = mutable_unit.movement_left();
|
||||
mutable_unit.set_movement(mutable_unit.total_movement());
|
||||
clear_shroud_unit(map,gamedata,units,i->first,teams,team);
|
||||
mutable_unit.set_movement(old_moves);
|
||||
}
|
||||
}
|
||||
|
||||
disp.recalculate_minimap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
std::string recruit_unit(const gamemap& map, int team,
|
||||
std::map<gamemap::location,unit>& units,
|
||||
unit& unit, gamemap::location preferred_location,
|
||||
display *disp=NULL);
|
||||
display *disp=NULL, bool need_castle=true);
|
||||
|
||||
struct battle_stats
|
||||
{
|
||||
|
@ -112,4 +112,7 @@ size_t move_unit(display* disp, const gamemap& map,
|
|||
const std::vector<gamemap::location>& steps,
|
||||
replay* move_recorder, undo_list* undos);
|
||||
|
||||
bool clear_shroud(display& disp, const gamemap& map, const game_data& gamedata,
|
||||
const unit_map& units, std::vector<team>& teams, int team);
|
||||
|
||||
#endif
|
||||
|
|
12
src/ai.cpp
12
src/ai.cpp
|
@ -103,7 +103,9 @@ void move_unit(const game_data& gameinfo, display& disp,
|
|||
paths current_paths = paths(map,gameinfo,units,from,teams,
|
||||
ignore_zocs,teleport);
|
||||
paths_wiper wiper(disp);
|
||||
disp.set_paths(¤t_paths);
|
||||
|
||||
if(!disp.shrouded(from.x,from.y))
|
||||
disp.set_paths(¤t_paths);
|
||||
|
||||
disp.scroll_to_tiles(from.x,from.y,to.x,to.y);
|
||||
|
||||
|
@ -402,6 +404,9 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
}
|
||||
|
||||
if(want_tower) {
|
||||
std::cerr << "trying to acquire village: " << i->first.x
|
||||
<< ", " << i->first.y << "\n";
|
||||
|
||||
const std::map<location,unit>::iterator un = units.find(i->second);
|
||||
if(un == units.end()) {
|
||||
assert(false);
|
||||
|
@ -419,7 +424,6 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
return;
|
||||
}
|
||||
}
|
||||
std::cout << "b\n";
|
||||
|
||||
//find units in need of healing
|
||||
std::map<location,unit>::iterator u_it = units.begin();
|
||||
|
@ -430,7 +434,7 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
//worth of healing, and doesn't regenerate itself, then try to
|
||||
//find a vacant village for it to rest in
|
||||
if(u.side() == team_num &&
|
||||
u.type().hitpoints() - u.hitpoints() >= game_config::heal_amount/2 &&
|
||||
u.type().hitpoints() - u.hitpoints() >= game_config::cure_amount/2 &&
|
||||
!u.type().regenerates()) {
|
||||
typedef std::multimap<location,location>::iterator Itor;
|
||||
std::pair<Itor,Itor> it = srcdst.equal_range(u_it->first);
|
||||
|
@ -440,6 +444,8 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
units.find(dst) == units.end()) {
|
||||
const location& src = it.first->first;
|
||||
|
||||
std::cerr << "moving unit to village for healing...\n";
|
||||
|
||||
move_unit(gameinfo,disp,map,units,src,dst,
|
||||
possible_moves,teams,team_num);
|
||||
do_move(disp,map,gameinfo,units,teams,team_num,state,
|
||||
|
|
|
@ -235,7 +235,7 @@ std::pair<location,location> choose_move(
|
|||
//now see if any other unit can put a better bid forward
|
||||
for(++u; u != units.end(); ++u) {
|
||||
if(u->second.side() != current_team || u->second.can_recruit() ||
|
||||
u->second.movement_left() <= 0) {
|
||||
u->second.movement_left() <= 0 || u->second.is_guardian()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ struct config
|
|||
const std::vector<line_source>* lines=0); //throws config::error
|
||||
std::string write() const;
|
||||
|
||||
std::map<std::string,std::string> values;
|
||||
string_map values;
|
||||
std::map<std::string,std::vector<config*> > children;
|
||||
|
||||
static std::vector<std::string> split(const std::string& val);
|
||||
|
|
163
src/display.cpp
163
src/display.cpp
|
@ -129,6 +129,10 @@ SDL_Rect display::screen_area() const
|
|||
|
||||
void display::select_hex(gamemap::location hex)
|
||||
{
|
||||
if(team_valid() && teams_[currentTeam_].shrouded(hex.x,hex.y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
invalidate(selectedHex_);
|
||||
selectedHex_ = hex;
|
||||
invalidate(selectedHex_);
|
||||
|
@ -203,13 +207,22 @@ void display::zoom(double amount)
|
|||
clear_surfaces(brightenedImages_);
|
||||
energy_bar_count_ = std::pair<int,int>(-1,-1);
|
||||
|
||||
const double orig_xpos = xpos_;
|
||||
const double orig_ypos = ypos_;
|
||||
|
||||
xpos_ /= zoom_;
|
||||
ypos_ /= zoom_;
|
||||
|
||||
const double max_zoom = 200.0;
|
||||
const double orig_zoom = zoom_;
|
||||
|
||||
zoom_ += amount;
|
||||
if(zoom_ > max_zoom)
|
||||
zoom_ = max_zoom;
|
||||
if(zoom_ > max_zoom) {
|
||||
zoom_ = orig_zoom;
|
||||
xpos_ = orig_xpos;
|
||||
ypos_ = orig_ypos;
|
||||
return;
|
||||
}
|
||||
|
||||
xpos_ *= zoom_;
|
||||
ypos_ *= zoom_;
|
||||
|
@ -217,8 +230,17 @@ void display::zoom(double amount)
|
|||
xpos_ += amount*2;
|
||||
ypos_ += amount*2;
|
||||
|
||||
const double prev_zoom = zoom_;
|
||||
|
||||
bounds_check_position();
|
||||
|
||||
if(zoom_ != prev_zoom) {
|
||||
xpos_ = orig_xpos;
|
||||
ypos_ = orig_ypos;
|
||||
zoom_ = orig_zoom;
|
||||
return;
|
||||
}
|
||||
|
||||
invalidate_all();
|
||||
}
|
||||
|
||||
|
@ -229,7 +251,7 @@ void display::default_zoom()
|
|||
|
||||
void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type)
|
||||
{
|
||||
if(update_locked())
|
||||
if(update_locked() || shrouded(x,y))
|
||||
return;
|
||||
|
||||
const double xpos = static_cast<double>(x)*zoom_*0.75 - xpos_;
|
||||
|
@ -440,7 +462,7 @@ void display::draw_sidebar()
|
|||
i = units_.find(selectedHex_);
|
||||
|
||||
if(i != units_.end())
|
||||
draw_unit_details(mapx()+2,int(390*sidebarScaling_),selectedHex_,
|
||||
draw_unit_details(mapx()+2,int(400*sidebarScaling_),selectedHex_,
|
||||
i->second,unitDescriptionRect_,unitProfileRect_);
|
||||
invalidateUnit_ = false;
|
||||
}
|
||||
|
@ -494,21 +516,29 @@ void display::draw_game_status(int x, int y)
|
|||
int nunits = 0;
|
||||
for(std::map<gamemap::location,unit>::const_iterator uit = units_.begin();
|
||||
uit != units_.end(); ++uit) {
|
||||
if(uit->second.side() == currentTeam_+1) {
|
||||
if(size_t(uit->second.side()) == currentTeam_+1) {
|
||||
++nunits;
|
||||
}
|
||||
}
|
||||
|
||||
const int income = teams_[currentTeam_].income() - nunits;
|
||||
|
||||
std::stringstream details;
|
||||
details << string_table["turn"] << ": " << status_.turn() << "/"
|
||||
<< status_.number_of_turns() << "\n" << string_table["gold"] << ": "
|
||||
<< teams_[currentTeam_].gold() << "\n"
|
||||
<< string_table["villages"] << ": "
|
||||
<< teams_[currentTeam_].towers().size() << "\n"
|
||||
<< string_table["units"] << ": " << nunits << "\n"
|
||||
<< string_table["income"] << ": " << income << "\n";
|
||||
|
||||
if(team_valid()) {
|
||||
const int upkeep = team_upkeep(units_,currentTeam_+1);
|
||||
|
||||
const int expenses = upkeep - teams_[currentTeam_].towers().size();
|
||||
const int income = teams_[currentTeam_].income() - maximum(expenses,0);
|
||||
|
||||
details << string_table["turn"] << ": " << status_.turn() << "/"
|
||||
<< status_.number_of_turns() << "\n"
|
||||
<< string_table["gold"] << ": "
|
||||
<< teams_[currentTeam_].gold() << "\n"
|
||||
<< string_table["villages"] << ": "
|
||||
<< teams_[currentTeam_].towers().size() << "\n"
|
||||
<< string_table["units"] << ": " << nunits << "\n"
|
||||
<< string_table["upkeep"] << ": " << upkeep << "\n"
|
||||
<< string_table["income"] << ": " << income << "\n";
|
||||
}
|
||||
|
||||
if(map_.on_board(mouseoverHex_)) {
|
||||
const gamemap::TERRAIN terrain = map_[mouseoverHex_.x][mouseoverHex_.y];
|
||||
|
@ -860,10 +890,12 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image,
|
|||
const int se_xpos = (int)get_location_x(se_loc);
|
||||
const int se_ypos = (int)get_location_y(se_loc);
|
||||
|
||||
const bool is_shrouded = shrouded(x,y);
|
||||
gamemap::TERRAIN terrain = gamemap::VOID_TERRAIN;
|
||||
|
||||
if(x >= 0 && y >= 0 && x < map_.x() && y < map_.y())
|
||||
if(map_.on_board(loc) && !is_shrouded) {
|
||||
terrain = map_[x][y];
|
||||
}
|
||||
|
||||
IMAGE_TYPE image_type = SCALED;
|
||||
|
||||
|
@ -887,14 +919,23 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image,
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<SDL_Surface*> overlaps = getAdjacentTerrain(x,y,image_type);
|
||||
typedef std::multimap<gamemap::location,std::string>::const_iterator Itor;
|
||||
for(std::pair<Itor,Itor> overlays =
|
||||
overlays_.equal_range(gamemap::location(x,y));
|
||||
overlays.first != overlays.second; ++overlays.first) {
|
||||
SDL_Surface* const overlay_surface = getImage(overlays.first->second);
|
||||
if(overlay_surface != NULL) {
|
||||
overlaps.push_back(overlay_surface);
|
||||
std::vector<SDL_Surface*> overlaps;
|
||||
|
||||
if(!is_shrouded) {
|
||||
overlaps = getAdjacentTerrain(x,y,image_type);
|
||||
|
||||
typedef std::multimap<gamemap::location,std::string>::const_iterator
|
||||
Itor;
|
||||
|
||||
for(std::pair<Itor,Itor> overlays =
|
||||
overlays_.equal_range(gamemap::location(x,y));
|
||||
overlays.first != overlays.second; ++overlays.first) {
|
||||
SDL_Surface* const overlay_surface =
|
||||
getImage(overlays.first->second);
|
||||
|
||||
if(overlay_surface != NULL) {
|
||||
overlaps.push_back(overlay_surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -939,8 +980,9 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image,
|
|||
|
||||
const char* energy_file = NULL;
|
||||
|
||||
if(it->second.side() != currentTeam_+1) {
|
||||
if(teams_[currentTeam_].is_enemy(it->second.side())) {
|
||||
if(size_t(it->second.side()) != currentTeam_+1) {
|
||||
if(team_valid() &&
|
||||
teams_[currentTeam_].is_enemy(it->second.side())) {
|
||||
energy_file = "enemy-energy.png";
|
||||
} else {
|
||||
energy_file = "ally-energy.png";
|
||||
|
@ -1118,7 +1160,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image,
|
|||
debugHighlights_[gamemap::location(x,y)],0);
|
||||
}
|
||||
|
||||
if(unit_image == NULL || energy_image == NULL)
|
||||
if(unit_image == NULL || energy_image == NULL || is_shrouded)
|
||||
return;
|
||||
|
||||
if(loc != hiddenUnit_) {
|
||||
|
@ -1527,8 +1569,11 @@ SDL_Surface* display::getMinimap(int w, int h)
|
|||
for(int y = 0; y != map_.y(); ++y) {
|
||||
for(int x = 0; x != map_.x(); ++x) {
|
||||
|
||||
*data = map_.get_terrain_info(map_[x][y]).get_rgb().
|
||||
format(surface->format);
|
||||
if(shrouded(x,y))
|
||||
*data = 0;
|
||||
else
|
||||
*data = map_.get_terrain_info(map_[x][y]).get_rgb().
|
||||
format(surface->format);
|
||||
++data;
|
||||
}
|
||||
|
||||
|
@ -1600,6 +1645,9 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
const gamemap::location& b, int damage,
|
||||
const attack_type& attack)
|
||||
{
|
||||
const bool hide = update_locked() || shrouded(a.x,a.y) && shrouded(b.x,b.y);
|
||||
|
||||
const unit_map::iterator att = units_.find(a);
|
||||
const unit_map::iterator def = units_.find(b);
|
||||
|
||||
def->second.set_defending(true,attack_type::LONG_RANGE);
|
||||
|
@ -1648,7 +1696,7 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!update_locked() && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
const std::string& sfx = hits ? sfx_it->on_hit : sfx_it->on_miss;
|
||||
if(sfx.empty() == false) {
|
||||
sound::play_sound(hits ? sfx_it->on_hit : sfx_it->on_miss);
|
||||
|
@ -1657,9 +1705,14 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
++sfx_it;
|
||||
}
|
||||
|
||||
const std::string* const unit_image = attack.get_frame(i);
|
||||
const std::string* unit_image = attack.get_frame(i);
|
||||
|
||||
if(!update_locked()) {
|
||||
if(unit_image == NULL) {
|
||||
unit_image =
|
||||
&att->second.type().image_fighting(attack_type::LONG_RANGE);
|
||||
}
|
||||
|
||||
if(!hide) {
|
||||
SDL_Surface* const image = (unit_image == NULL) ?
|
||||
NULL : getImage(*unit_image);
|
||||
draw_tile(a.x,a.y,image);
|
||||
|
@ -1692,7 +1745,7 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
|
||||
draw_tile(b.x,b.y,NULL,defensive_alpha,defensive_colour);
|
||||
|
||||
if(i >= 0 && i < real_last_missile && !update_locked()) {
|
||||
if(i >= 0 && i < real_last_missile && !hide) {
|
||||
const int missile_frame = i + first_missile;
|
||||
|
||||
const std::string* missile_image
|
||||
|
@ -1721,7 +1774,7 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
}
|
||||
|
||||
const int wait_time = ticks + time_resolution - SDL_GetTicks();
|
||||
if(wait_time > 0 && !turbo() && !update_locked())
|
||||
if(wait_time > 0 && !turbo() && !hide)
|
||||
SDL_Delay(wait_time);
|
||||
|
||||
ticks = SDL_GetTicks();
|
||||
|
@ -1740,7 +1793,7 @@ bool display::unit_attack_ranged(const gamemap::location& a,
|
|||
|
||||
void display::unit_die(const gamemap::location& loc, SDL_Surface* image)
|
||||
{
|
||||
if(update_locked())
|
||||
if(update_locked() || shrouded(loc.x,loc.y))
|
||||
return;
|
||||
|
||||
const int frame_time = 30;
|
||||
|
@ -1764,6 +1817,8 @@ bool display::unit_attack(const gamemap::location& a,
|
|||
const gamemap::location& b, int damage,
|
||||
const attack_type& attack)
|
||||
{
|
||||
const bool hide = update_locked() || shrouded(a.x,a.y) && shrouded(b.x,b.y);
|
||||
|
||||
log_scope("unit_attack");
|
||||
invalidate_all();
|
||||
draw(true,true);
|
||||
|
@ -1823,7 +1878,7 @@ bool display::unit_attack(const gamemap::location& a,
|
|||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!update_locked() && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
const std::string& sfx = hits ? sfx_it->on_hit : sfx_it->on_miss;
|
||||
if(sfx.empty() == false) {
|
||||
sound::play_sound(hits ? sfx_it->on_hit : sfx_it->on_miss);
|
||||
|
@ -1874,11 +1929,11 @@ bool display::unit_attack(const gamemap::location& a,
|
|||
const int posx = int(pos*xsrc + (1.0-pos)*xdst) + xoffset;
|
||||
const int posy = int(pos*ysrc + (1.0-pos)*ydst);
|
||||
|
||||
if(image != NULL && !update_locked())
|
||||
if(image != NULL && !hide)
|
||||
draw_unit(posx,posy,image,attacker.facing_left());
|
||||
|
||||
const int wait_time = ticks + time_resolution - SDL_GetTicks();
|
||||
if(wait_time > 0 && !turbo() && !update_locked())
|
||||
if(wait_time > 0 && !turbo() && !hide)
|
||||
SDL_Delay(wait_time);
|
||||
|
||||
ticks = SDL_GetTicks();
|
||||
|
@ -1900,7 +1955,9 @@ void display::move_unit_between(const gamemap::location& a,
|
|||
const gamemap::location& b,
|
||||
const unit& u)
|
||||
{
|
||||
if(update_locked())
|
||||
if(update_locked() || team_valid()
|
||||
&& teams_[currentTeam_].shrouded(a.x,a.y)
|
||||
&& teams_[currentTeam_].shrouded(b.x,b.y))
|
||||
return;
|
||||
|
||||
const bool face_left = u.facing_left();
|
||||
|
@ -2060,12 +2117,17 @@ void display::draw_unit(int x, int y, SDL_Surface* image,
|
|||
|
||||
surface_lock screen_lock(screen);
|
||||
|
||||
const Pixel ShroudColour = 0;
|
||||
|
||||
for(; y != endy; ++y, src += src_increment) {
|
||||
Pixel* dst = screen_lock.pixels() + y*screen->w + x;
|
||||
|
||||
if(alpha == 1.0) {
|
||||
if(reverse) {
|
||||
for(int i = xoffset; i != len; ++i) {
|
||||
if(dst[i-xoffset] == ShroudColour)
|
||||
continue;
|
||||
|
||||
if(src[i] == semi_trans)
|
||||
dst[i-xoffset] = alpha_blend_pixels(
|
||||
0,dst[i-xoffset],fmt,0.5);
|
||||
|
@ -2074,6 +2136,9 @@ void display::draw_unit(int x, int y, SDL_Surface* image,
|
|||
}
|
||||
} else {
|
||||
for(int i = image->w-1-xoffset; i != image->w-len-1; --i,++dst){
|
||||
if(*dst == ShroudColour)
|
||||
continue;
|
||||
|
||||
if(src[i] == semi_trans)
|
||||
*dst = alpha_blend_pixels(0,*dst,fmt,0.5);
|
||||
else if(src[i] != 0)
|
||||
|
@ -2083,6 +2148,9 @@ void display::draw_unit(int x, int y, SDL_Surface* image,
|
|||
} else {
|
||||
if(reverse) {
|
||||
for(int i = xoffset; i != len; ++i) {
|
||||
if(dst[i-xoffset] == ShroudColour)
|
||||
continue;
|
||||
|
||||
const Pixel blend = blendto ? blendto : dst[i-xoffset];
|
||||
|
||||
if(src[i] != 0)
|
||||
|
@ -2091,6 +2159,9 @@ void display::draw_unit(int x, int y, SDL_Surface* image,
|
|||
}
|
||||
} else {
|
||||
for(int i = image->w-1-xoffset; i != image->w-len-1; --i,++dst){
|
||||
if(*dst == ShroudColour)
|
||||
continue;
|
||||
|
||||
const Pixel blend = blendto ? blendto : *dst;
|
||||
if(src[i] != 0)
|
||||
*dst = alpha_blend_pixels(src[i],blend,fmt,alpha);
|
||||
|
@ -2172,8 +2243,9 @@ void display::remove_overlay(const gamemap::location& loc)
|
|||
overlays_.erase(loc);
|
||||
}
|
||||
|
||||
void display::set_team(int team)
|
||||
void display::set_team(size_t team)
|
||||
{
|
||||
assert(team < teams_.size());
|
||||
currentTeam_ = team;
|
||||
}
|
||||
|
||||
|
@ -2226,3 +2298,16 @@ void display::clear_debug_highlights()
|
|||
{
|
||||
debugHighlights_.clear();
|
||||
}
|
||||
|
||||
bool display::shrouded(int x, int y) const
|
||||
{
|
||||
if(team_valid())
|
||||
return teams_[currentTeam_].shrouded(x,y);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool display::team_valid() const
|
||||
{
|
||||
return currentTeam_ < teams_.size();
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
void draw_terrain_palette(int x, int y, gamemap::TERRAIN selected);
|
||||
gamemap::TERRAIN get_terrain_on(int palx, int paly, int x, int y);
|
||||
|
||||
void set_team(int team);
|
||||
void set_team(size_t team);
|
||||
|
||||
void set_advancing_unit(const gamemap::location& loc, double amount);
|
||||
|
||||
|
@ -117,6 +117,8 @@ public:
|
|||
static void debug_highlight(const gamemap::location& loc, double amount);
|
||||
static void clear_debug_highlights();
|
||||
|
||||
bool shrouded(int x, int y) const;
|
||||
|
||||
private:
|
||||
display(const display&);
|
||||
void operator=(const display&);
|
||||
|
@ -182,6 +184,8 @@ private:
|
|||
|
||||
const gamestatus& status_;
|
||||
|
||||
bool team_valid() const;
|
||||
|
||||
const std::vector<team>& teams_;
|
||||
|
||||
int lastDraw_;
|
||||
|
@ -200,7 +204,7 @@ private:
|
|||
bool sideBarBgDrawn_;
|
||||
int lastTimeOfDay_;
|
||||
|
||||
int currentTeam_;
|
||||
size_t currentTeam_;
|
||||
|
||||
//used to store a unit that is not drawn, because it's currently
|
||||
//being moved or otherwise changed
|
||||
|
|
|
@ -118,7 +118,7 @@ SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
|
|||
return res;
|
||||
}
|
||||
|
||||
SDL_Surface* const surface = TTF_RenderText_Blended(font,text.c_str(),col);
|
||||
scoped_sdl_surface surface(TTF_RenderText_Blended(font,text.c_str(),col));
|
||||
if(surface == NULL) {
|
||||
std::cerr << "Could not render ttf: '" << text << "'\n";
|
||||
SDL_Rect res;
|
||||
|
@ -147,8 +147,6 @@ SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
|
|||
SDL_BlitSurface(surface,&src,gui->video().getSurface(),&dest);
|
||||
}
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,10 +142,7 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
|
||||
int play_game(int argc, char** argv)
|
||||
{
|
||||
std::string text_chr = read_file("data/text.chr");
|
||||
text_chr.resize(256*8);
|
||||
|
||||
CVideo video(text_chr.c_str());
|
||||
CVideo video;
|
||||
const font::manager font_manager;
|
||||
const sound::manager sound_manager;
|
||||
const preferences::manager prefs_manager;
|
||||
|
|
|
@ -16,12 +16,12 @@ namespace game_config
|
|||
{
|
||||
const int unit_cost = 1;
|
||||
const int base_income = 2;
|
||||
const int tower_income = 2;
|
||||
const int tower_income = 1;
|
||||
const int heal_amount = 4;
|
||||
const int healer_heals_per_turn = 8;
|
||||
const int cure_amount = 8;
|
||||
const int curer_heals_per_turn = 18;
|
||||
const int recall_cost = 20;
|
||||
const std::string version = "0.4.8";
|
||||
const std::string version = "0.4.9-CVS";
|
||||
bool debug = false;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "language.hpp"
|
||||
#include "playlevel.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "sound.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <deque>
|
||||
|
@ -55,8 +56,8 @@ bool conditional_passed(game_state& state_of_game,
|
|||
std::vector<config*>& variables = cond.children["variable"];
|
||||
for(std::vector<config*>::iterator var = variables.begin();
|
||||
var != variables.end(); ++var) {
|
||||
std::map<std::string,std::string>& values = (*var)->values;
|
||||
std::map<std::string,std::string>& vars = state_of_game.variables;
|
||||
string_map& values = (*var)->values;
|
||||
string_map& vars = state_of_game.variables;
|
||||
const std::string& name = values["name"];
|
||||
|
||||
//if we don't have a record of the variable, then the statement
|
||||
|
@ -74,7 +75,7 @@ bool conditional_passed(game_state& state_of_game,
|
|||
const std::string& value = vars[name];
|
||||
const double num_value = atof(value.c_str());
|
||||
|
||||
std::map<std::string,std::string>::iterator itor;
|
||||
string_map::iterator itor;
|
||||
|
||||
itor = values.find("equals");
|
||||
if(itor != values.end() && itor->second != value) {
|
||||
|
@ -127,6 +128,7 @@ namespace {
|
|||
display* screen = NULL;
|
||||
gamemap* game_map = NULL;
|
||||
std::map<gamemap::location,unit>* units = NULL;
|
||||
std::vector<team>* teams = NULL;
|
||||
game_state* state_of_game = NULL;
|
||||
game_data* game_data_ptr = NULL;
|
||||
|
||||
|
@ -191,11 +193,32 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
handle_event(event_info,*cmd);
|
||||
}
|
||||
|
||||
//sounds
|
||||
std::vector<config*>& sounds = cfg->children["sound"];
|
||||
for(std::vector<config*>::iterator sfx = sounds.begin();
|
||||
sfx != sounds.end(); ++sfx) {
|
||||
sound::play_sound((*sfx)->values["name"]);
|
||||
}
|
||||
|
||||
//an award of gold to a particular side
|
||||
std::vector<config*>& gold = cfg->children["gold"];
|
||||
for(std::vector<config*>::iterator gd = gold.begin(); gd!=gold.end();++gd) {
|
||||
string_map& values = (*gd)->values;
|
||||
const std::string& side = values["side"];
|
||||
const std::string& amount = values["amount"];
|
||||
const int side_num = side.empty() ? 1 : atoi(side.c_str());
|
||||
const int amount_num = atoi(amount.c_str());
|
||||
const size_t team_index = side_num-1;
|
||||
if(team_index < teams->size()) {
|
||||
(*teams)[team_index].spend_gold(-amount_num);
|
||||
}
|
||||
}
|
||||
|
||||
//setting a variable
|
||||
std::vector<config*>& set_vars = cfg->children["set_variable"];
|
||||
for(std::vector<config*>::iterator var = set_vars.begin();
|
||||
var != set_vars.end(); ++var) {
|
||||
std::map<std::string,std::string>& vals = (*var)->values;
|
||||
string_map& vals = (*var)->values;
|
||||
const std::string& name = vals["name"];
|
||||
const std::string& value = vals["value"];
|
||||
if(value.empty() == false) {
|
||||
|
@ -341,7 +364,8 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
for(std::vector<unit>::iterator u = avail.begin();
|
||||
u != avail.end(); ++u) {
|
||||
if(u->matches_filter(**ir)) {
|
||||
recruit_unit(*game_map,1,*units,*u,gamemap::location(),screen);
|
||||
recruit_unit(*game_map,1,*units,*u,gamemap::location(),
|
||||
screen,false);
|
||||
u = avail.erase(u);
|
||||
if(u == avail.end())
|
||||
break;
|
||||
|
@ -352,7 +376,7 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
std::vector<config*>& objects = cfg->children["object"];
|
||||
for(std::vector<config*>::iterator obj = objects.begin();
|
||||
obj != objects.end(); ++obj) {
|
||||
std::map<std::string,std::string>& values = (*obj)->values;
|
||||
string_map& values = (*obj)->values;
|
||||
|
||||
//if this item has already been used
|
||||
if(values["used"].empty() == false)
|
||||
|
@ -414,7 +438,8 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
std::vector<config*>& messages = cfg->children["message"];
|
||||
for(std::vector<config*>::iterator msg = messages.begin();
|
||||
msg != messages.end(); ++msg) {
|
||||
std::map<std::string,std::string>& values = (*msg)->values;
|
||||
string_map& values = (*msg)->values;
|
||||
|
||||
std::map<gamemap::location,unit>::iterator speaker = units->end();
|
||||
if(values["speaker"] == "unit") {
|
||||
speaker = units->find(event_info.loc1);
|
||||
|
@ -434,6 +459,11 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
}
|
||||
|
||||
const string_map::const_iterator sfx = values.find("sound");
|
||||
if(sfx != values.end()) {
|
||||
sound::play_sound(sfx->second);
|
||||
}
|
||||
|
||||
const std::string& id = values["id"];
|
||||
|
||||
std::string image = (*msg)->values["image"];
|
||||
|
@ -665,6 +695,7 @@ namespace game_events {
|
|||
|
||||
manager::manager(config& cfg, display& gui_, gamemap& map_,
|
||||
std::map<gamemap::location,unit>& units_,
|
||||
std::vector<team>& teams_,
|
||||
game_state& state_of_game_, game_data& game_data_)
|
||||
{
|
||||
std::vector<config*>& events_list = cfg.children["event"];
|
||||
|
@ -675,6 +706,7 @@ manager::manager(config& cfg, display& gui_, gamemap& map_,
|
|||
new_handler.name(), new_handler));
|
||||
}
|
||||
|
||||
teams = &teams_;
|
||||
screen = &gui_;
|
||||
game_map = &map_;
|
||||
units = &units_;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "display.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "map.hpp"
|
||||
#include "team.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "unit_types.hpp"
|
||||
|
||||
|
@ -31,7 +32,7 @@ bool conditional_passed(game_state& state_of_game,
|
|||
|
||||
struct manager {
|
||||
manager(config& cfg, display& disp, gamemap& map,
|
||||
std::map<gamemap::location,unit>& units,
|
||||
std::map<gamemap::location,unit>& units, std::vector<team>& teams,
|
||||
game_state& state_of_game, game_data& data);
|
||||
~manager();
|
||||
};
|
||||
|
|
|
@ -45,6 +45,7 @@ HOTKEY_COMMAND string_to_command(const std::string& str)
|
|||
m.insert(val("save",HOTKEY_SAVE_GAME));
|
||||
m.insert(val("recruit",HOTKEY_RECRUIT));
|
||||
m.insert(val("recall",HOTKEY_RECALL));
|
||||
m.insert(val("endturn",HOTKEY_ENDTURN));
|
||||
}
|
||||
|
||||
const std::map<std::string,HOTKEY_COMMAND>::const_iterator i = m.find(str);
|
||||
|
|
|
@ -23,7 +23,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
|
|||
HOTKEY_FULLSCREEN, HOTKEY_ACCELERATED,
|
||||
HOTKEY_TERRAIN_TABLE, HOTKEY_ATTACK_RESISTANCE,
|
||||
HOTKEY_UNIT_DESCRIPTION, HOTKEY_SAVE_GAME,
|
||||
HOTKEY_RECRUIT, HOTKEY_RECALL,
|
||||
HOTKEY_RECRUIT, HOTKEY_RECALL, HOTKEY_ENDTURN,
|
||||
HOTKEY_NULL };
|
||||
|
||||
void add_hotkeys(config& cfg);
|
||||
|
|
|
@ -250,7 +250,7 @@ shortest_path_calculator::shortest_path_calculator(const unit& u, const team& t,
|
|||
double shortest_path_calculator::cost(const gamemap::location& loc,
|
||||
double so_far) const
|
||||
{
|
||||
if(!map_.on_board(loc))
|
||||
if(!map_.on_board(loc) || team_.shrouded(loc.x,loc.y))
|
||||
return 100000.0;
|
||||
|
||||
const unit_map::const_iterator enemy_unit = units_.find(loc);
|
||||
|
|
|
@ -51,7 +51,8 @@ struct paths
|
|||
int move_left;
|
||||
};
|
||||
|
||||
std::map<gamemap::location,route> routes;
|
||||
typedef std::map<gamemap::location,route> routes_map;
|
||||
routes_map routes;
|
||||
};
|
||||
|
||||
struct shortest_path_calculator
|
||||
|
|
|
@ -32,8 +32,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
gamemap map(terrain_config,read_file("data/maps/" + level->values["map"]));
|
||||
|
||||
CKey key;
|
||||
typedef std::map<gamemap::location,unit> units_map;
|
||||
units_map units;
|
||||
unit_map units;
|
||||
|
||||
std::vector<team> teams;
|
||||
|
||||
|
@ -99,7 +98,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
sound::play_music(music);
|
||||
}
|
||||
|
||||
game_events::manager events_manager(*level,gui,map,units,
|
||||
game_events::manager events_manager(*level,gui,map,units,teams,
|
||||
state_of_game,gameinfo);
|
||||
|
||||
//find a list of 'items' (i.e. overlays) on the level, and add them
|
||||
|
@ -110,7 +109,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
(*overlay)->values["image"]);
|
||||
}
|
||||
|
||||
for(units_map::iterator i = units.begin(); i != units.end(); ++i) {
|
||||
for(unit_map::iterator i = units.begin(); i != units.end(); ++i) {
|
||||
i->second.new_turn();
|
||||
}
|
||||
|
||||
|
@ -124,6 +123,8 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
try {
|
||||
|
||||
if(first_time) {
|
||||
clear_shroud(gui,map,gameinfo,units,teams,0);
|
||||
|
||||
update_locker lock_display(gui,recorder.skipping());
|
||||
game_events::fire("start");
|
||||
gui.draw();
|
||||
|
@ -135,10 +136,12 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
team_it != teams.end(); ++team_it) {
|
||||
const int player_number = (team_it - teams.begin()) + 1;
|
||||
|
||||
clear_shroud(gui,map,gameinfo,units,teams,player_number-1);
|
||||
|
||||
calculate_healing(gui,map,units,player_number);
|
||||
|
||||
//scroll the map to the leader
|
||||
const units_map::iterator leader =
|
||||
const unit_map::iterator leader =
|
||||
find_leader(units,player_number);
|
||||
|
||||
if(leader != units.end() && !recorder.skipping()) {
|
||||
|
@ -175,7 +178,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
SDL_Delay(1000);
|
||||
}
|
||||
|
||||
for(units_map::iterator uit = units.begin();
|
||||
for(unit_map::iterator uit = units.begin();
|
||||
uit != units.end(); ++uit) {
|
||||
if(uit->second.side() == player_number)
|
||||
uit->second.end_turn();
|
||||
|
@ -206,18 +209,25 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
}
|
||||
|
||||
std::map<int,int> expenditure;
|
||||
for(units_map::iterator i = units.begin();
|
||||
for(unit_map::iterator i = units.begin();
|
||||
i != units.end(); ++i) {
|
||||
i->second.new_turn();
|
||||
expenditure[i->second.side()]++;
|
||||
}
|
||||
|
||||
int team_num = 1;
|
||||
for(std::vector<team>::iterator it = teams.begin();
|
||||
it != teams.end(); ++it, ++team_num) {
|
||||
it->new_turn();
|
||||
it->spend_gold(expenditure[team_num]);
|
||||
|
||||
//if the expense is less than the number of villages owned,
|
||||
//then we don't have to pay anything at all
|
||||
const int expense = team_upkeep(units,team_num) -
|
||||
it->towers().size();
|
||||
if(expense > 0) {
|
||||
it->spend_gold(expense);
|
||||
}
|
||||
}
|
||||
|
||||
} catch(end_level_exception& end_level) {
|
||||
|
||||
if(end_level.result == QUIT || end_level.result == REPLAY) {
|
||||
|
@ -255,7 +265,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
const int turns_left = status.number_of_turns() - status.turn();
|
||||
const int finishing_bonus = end_level.gold_bonus ?
|
||||
(finishing_bonus_per_turn * turns_left) : 0;
|
||||
state_of_game.gold = (remaining_gold+finishing_bonus)/2;
|
||||
state_of_game.gold = ((remaining_gold+finishing_bonus)*80)/100;
|
||||
|
||||
gui::show_dialog(gui,NULL,string_table["victory_heading"],
|
||||
string_table["victory_message"],gui::OK_ONLY);
|
||||
|
|
|
@ -179,6 +179,12 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
|
||||
unit_map::iterator u = units.find(selected_hex);
|
||||
|
||||
//if the unit is selected and then itself clicked on,
|
||||
//any goto command is cancelled
|
||||
if(selected_hex == hex && u->second.side() == team_num) {
|
||||
u->second.set_goto(gamemap::location());
|
||||
}
|
||||
|
||||
//if we can move to that tile
|
||||
std::map<gamemap::location,paths::route>::const_iterator
|
||||
route = enemy_paths ? current_paths.routes.end() :
|
||||
|
@ -229,13 +235,13 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
att << attack_name << " (" << attack_type
|
||||
<< ") " << stats.damage_defender_takes << "-"
|
||||
<< stats.nattacks << " " << range << " "
|
||||
<< int(ceil(100.0*stats.chance_to_hit_defender)) << "%";
|
||||
<< int(round(100.0*stats.chance_to_hit_defender))<< "%";
|
||||
|
||||
att << "," << string_table["versus"] << ",";
|
||||
att << defend_name << " (" << defend_type
|
||||
<< ") " << stats.damage_attacker_takes << "-"
|
||||
<< stats.ndefends << " "
|
||||
<< int(ceil(100.0*stats.chance_to_hit_attacker)) << "%";
|
||||
<< int(round(100.0*stats.chance_to_hit_attacker))<< "%";
|
||||
|
||||
items.push_back(att.str());
|
||||
units_list.push_back(enemy->second);
|
||||
|
@ -307,6 +313,7 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
|
||||
const size_t moves = move_unit(&gui,map,units,teams,
|
||||
current_route.steps,&recorder,&undo_stack);
|
||||
|
||||
redo_stack.clear();
|
||||
|
||||
selected_hex = gamemap::location();
|
||||
|
@ -341,6 +348,9 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
gui.set_paths(¤t_paths);
|
||||
}
|
||||
|
||||
if(clear_shroud(gui,map,gameinfo,units,teams,team_num-1)) {
|
||||
undo_stack.clear();
|
||||
}
|
||||
} else {
|
||||
gui.set_paths(NULL);
|
||||
current_paths = paths();
|
||||
|
@ -411,9 +421,7 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
}
|
||||
|
||||
else if(result == string_table["end_turn"]) {
|
||||
recorder.save_game(gameinfo,string_table["auto_save"]);
|
||||
recorder.end_turn();
|
||||
return;
|
||||
command = HOTKEY_ENDTURN;
|
||||
}
|
||||
|
||||
else if(result == string_table["scenario_objectives"]) {
|
||||
|
@ -484,6 +492,12 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
if(command == HOTKEY_NULL)
|
||||
command = check_keys(gui);
|
||||
|
||||
if(command == HOTKEY_ENDTURN) {
|
||||
recorder.save_game(gameinfo,string_table["auto_save"]);
|
||||
recorder.end_turn();
|
||||
return;
|
||||
}
|
||||
|
||||
if(command == HOTKEY_RECRUIT) {
|
||||
std::vector<unit> sample_units;
|
||||
|
||||
|
@ -679,10 +693,15 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
prefix = "#";
|
||||
}
|
||||
|
||||
const int resist=int(100.0-ceil(100.0*resistance));
|
||||
const int resist = 100 - int(round(100.0*resistance));
|
||||
|
||||
const std::string& lang_weapon =
|
||||
string_table["weapon_type_" + i->first];
|
||||
const std::string& weap = lang_weapon.empty() ? i->first :
|
||||
lang_weapon;
|
||||
|
||||
std::stringstream str;
|
||||
str << i->first << "," << prefix << resist << "%";
|
||||
str << weap << "," << prefix << resist << "%";
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
|
@ -692,7 +711,7 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
gui.getImage(un->second.type().image_profile(),display::UNSCALED);
|
||||
gui::show_dialog(gui,unit_image,
|
||||
un->second.type().language_name(),
|
||||
"Unit resistance table",
|
||||
string_table["unit_resistance_table"],
|
||||
gui::MESSAGE,&items,&units_list);
|
||||
}
|
||||
|
||||
|
@ -719,7 +738,7 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
|
|||
|
||||
const double defense = move_type.defense_modifier(map,*t);
|
||||
|
||||
const int def = int(100.0-ceil(100.0*defense));
|
||||
const int def = 100-int(round(100.0*defense));
|
||||
|
||||
std::stringstream str;
|
||||
str << lang_name << ",";
|
||||
|
|
|
@ -414,6 +414,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
}
|
||||
|
||||
game_events::fire("moveto",dst);
|
||||
|
||||
clear_shroud(disp,map,gameinfo,units,teams,team_num-1);
|
||||
}
|
||||
|
||||
else if((it = cfg->children.find("attack")) != cfg->children.end()) {
|
||||
|
|
35
src/team.cpp
35
src/team.cpp
|
@ -89,6 +89,8 @@ team::team_info::team_info(config& cfg)
|
|||
tgt != tgts.end(); ++tgt) {
|
||||
targets.push_back(target(**tgt));
|
||||
}
|
||||
|
||||
use_shroud = (cfg.values["shroud"] == "yes");
|
||||
}
|
||||
|
||||
team::team(config& cfg, int gold) : gold_(gold), info_(cfg)
|
||||
|
@ -191,3 +193,36 @@ std::vector<team::target>& team::targets()
|
|||
{
|
||||
return info_.targets;
|
||||
}
|
||||
|
||||
bool team::uses_shroud() const
|
||||
{
|
||||
return info_.use_shroud;
|
||||
}
|
||||
|
||||
bool team::shrouded(size_t x, size_t y) const
|
||||
{
|
||||
if(info_.use_shroud == false)
|
||||
return false;
|
||||
|
||||
if(x >= shroud_.size())
|
||||
return true;
|
||||
|
||||
if(y >= shroud_[x].size())
|
||||
return true;
|
||||
|
||||
return !shroud_[x][y];
|
||||
}
|
||||
|
||||
void team::clear_shroud(size_t x, size_t y)
|
||||
{
|
||||
if(info_.use_shroud == false)
|
||||
return;
|
||||
|
||||
if(x >= shroud_.size())
|
||||
shroud_.resize(x+1);
|
||||
|
||||
if(y >= shroud_[x].size())
|
||||
shroud_[x].resize(y+1);
|
||||
|
||||
shroud_[x][y] = true;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
double leader_value, village_value;
|
||||
|
||||
std::vector<target> targets;
|
||||
|
||||
bool use_shroud;
|
||||
};
|
||||
|
||||
team(config& cfg, int gold=100);
|
||||
|
@ -74,10 +76,16 @@ public:
|
|||
int villages_per_scout() const;
|
||||
|
||||
std::vector<target>& targets();
|
||||
|
||||
bool uses_shroud() const;
|
||||
bool shrouded(size_t x, size_t y) const;
|
||||
void clear_shroud(size_t x, size_t y);
|
||||
private:
|
||||
int gold_;
|
||||
std::set<gamemap::location> towers_;
|
||||
|
||||
std::vector<std::vector<bool> > shroud_;
|
||||
|
||||
team_info info_;
|
||||
};
|
||||
|
||||
|
|
34
src/unit.cpp
34
src/unit.cpp
|
@ -45,7 +45,7 @@ bool compare_unit_values::operator()(const unit& a, const unit& b) const
|
|||
unit::unit(game_data& data, config& cfg) : state_(STATE_NORMAL),
|
||||
moves_(0), facingLeft_(true),
|
||||
recruit_(false),
|
||||
guardian_(false)
|
||||
guardian_(false), loyal_(false)
|
||||
{
|
||||
read(data,cfg);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ unit::unit(const unit_type* t, int side, bool use_traits) :
|
|||
backupMaxMovement_(t->movement()),
|
||||
recruit_(false), attacks_(t->attacks()),
|
||||
backupAttacks_(t->attacks()),
|
||||
guardian_(false)
|
||||
guardian_(false), loyal_(false)
|
||||
{
|
||||
//calculate the unit's traits
|
||||
std::vector<config*> traits = t->possible_traits();
|
||||
|
@ -113,7 +113,7 @@ unit::unit(const unit_type* t, const unit& u) :
|
|||
attacks_(t->attacks()), backupAttacks_(t->attacks()),
|
||||
modifications_(u.modifications_),
|
||||
traitsDescription_(u.traitsDescription_),
|
||||
guardian_(false)
|
||||
guardian_(false), loyal_(false)
|
||||
{
|
||||
//apply modifications etc, refresh the unit
|
||||
new_level();
|
||||
|
@ -491,7 +491,7 @@ const std::string& unit::image() const
|
|||
attackType_->get_frame(attackingMilliseconds_);
|
||||
|
||||
if(img == NULL)
|
||||
return type_->image();
|
||||
return type_->image_fighting(attackType_->range());
|
||||
else
|
||||
return *img;
|
||||
}
|
||||
|
@ -639,6 +639,8 @@ void unit::add_modification(const std::string& type, config& mod, bool no_add)
|
|||
if(maxExperience_ < 1) {
|
||||
maxExperience_ = 1;
|
||||
}
|
||||
} else if(apply_to == "loyal") {
|
||||
loyal_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,3 +656,27 @@ void unit::apply_modifications()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int unit::upkeep() const
|
||||
{
|
||||
//special units with descriptions don't have any upkeep,
|
||||
//as they are major units, not hired units
|
||||
if(description_.empty() == false)
|
||||
return 0;
|
||||
|
||||
//loyal units always have an upkeep of 1 gold. Other units have an
|
||||
//upkeep equal to their level
|
||||
return loyal_ ? 1 : type().level();
|
||||
}
|
||||
|
||||
int team_upkeep(const unit_map& units, int side)
|
||||
{
|
||||
int res = 0;
|
||||
for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() == side) {
|
||||
res += i->second.upkeep();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,8 @@ public:
|
|||
const gamemap::location& get_goto() const;
|
||||
void set_goto(const gamemap::location& new_goto);
|
||||
|
||||
int upkeep() const;
|
||||
|
||||
void add_modification(const std::string& type, config& modification,
|
||||
bool no_add=false);
|
||||
|
||||
|
@ -138,6 +140,8 @@ private:
|
|||
|
||||
gamemap::location goto_;
|
||||
|
||||
bool loyal_;
|
||||
|
||||
void apply_modifications();
|
||||
};
|
||||
|
||||
|
@ -148,4 +152,6 @@ struct compare_unit_values
|
|||
|
||||
typedef std::map<gamemap::location,unit> unit_map;
|
||||
|
||||
int team_upkeep(const unit_map& units, int team_num);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -396,6 +396,21 @@ const std::string& unit_type::image() const
|
|||
return cfg_.values["image"];
|
||||
}
|
||||
|
||||
const std::string& unit_type::image_fighting(attack_type::RANGE range) const
|
||||
{
|
||||
static const std::string short_range("image_short");
|
||||
static const std::string long_range("image_long");
|
||||
|
||||
const std::string& str = range == attack_type::LONG_RANGE ?
|
||||
long_range : short_range;
|
||||
const std::string& val = cfg_.values[str];
|
||||
|
||||
if(!val.empty())
|
||||
return val;
|
||||
else
|
||||
return image();
|
||||
}
|
||||
|
||||
const std::string& unit_type::image_defensive(attack_type::RANGE range) const
|
||||
{
|
||||
{
|
||||
|
|
|
@ -129,6 +129,7 @@ public:
|
|||
const std::string& name() const;
|
||||
const std::string& image() const;
|
||||
const std::string& image_profile() const;
|
||||
const std::string& image_fighting(attack_type::RANGE range) const;
|
||||
const std::string& image_defensive(attack_type::RANGE range) const;
|
||||
const std::string& unit_description() const;
|
||||
int hitpoints() const;
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
CVideo::CVideo(const char* text) : frameBuffer(NULL)
|
||||
CVideo::CVideo() : frameBuffer(NULL)
|
||||
{
|
||||
const int res =
|
||||
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
|
||||
|
@ -85,13 +85,9 @@ CVideo::CVideo(const char* text) : frameBuffer(NULL)
|
|||
std::cerr << "Could not initialize SDL: " << SDL_GetError() << "\n";
|
||||
throw CVideo::error();
|
||||
}
|
||||
|
||||
for(int i = 0; i != sizeof(text_); ++i) {
|
||||
text_[i] = text[i];
|
||||
}
|
||||
}
|
||||
|
||||
CVideo::CVideo( int x, int y, int bits_per_pixel, int flags, const char* text )
|
||||
CVideo::CVideo( int x, int y, int bits_per_pixel, int flags)
|
||||
: frameBuffer(NULL)
|
||||
{
|
||||
const int res = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
|
||||
|
@ -100,10 +96,6 @@ CVideo::CVideo( int x, int y, int bits_per_pixel, int flags, const char* text )
|
|||
}
|
||||
|
||||
setMode( x, y, bits_per_pixel, flags );
|
||||
|
||||
for(int i = 0; i != sizeof(text_); ++i) {
|
||||
text_[i] = text[i];
|
||||
}
|
||||
}
|
||||
|
||||
CVideo::~CVideo()
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
class CVideo {
|
||||
public:
|
||||
CVideo(const char* text);
|
||||
CVideo( int x, int y, int bits_per_pixel, int flags, const char* text );
|
||||
CVideo();
|
||||
CVideo(int x, int y, int bits_per_pixel, int flags);
|
||||
~CVideo();
|
||||
|
||||
int modePossible( int x, int y, int bits_per_pixel, int flags );
|
||||
|
@ -56,7 +56,6 @@ class CVideo {
|
|||
private:
|
||||
|
||||
SDL_Surface* frameBuffer;
|
||||
char text_[256*8];
|
||||
};
|
||||
|
||||
void allow_resizing(bool);
|
||||
|
|
Loading…
Add table
Reference in a new issue