v0.6rc3
This commit is contained in:
parent
27a1a5d41f
commit
5c890a420f
49 changed files with 963 additions and 325 deletions
13
changelog
13
changelog
|
@ -1,9 +1,9 @@
|
|||
Version 0.6:
|
||||
* radical storyline changes, this breaks saves from older versions
|
||||
* fog of war
|
||||
* support for multiple campaigns
|
||||
* enemy units do not vanish anymore when enemy leader is killed
|
||||
* new scenarios for 'Heir to the Throne' (Konrad's Tale):
|
||||
* Isle of the Damned
|
||||
* Northern Winter
|
||||
* The Lost General
|
||||
* Hasty Alliance
|
||||
|
@ -17,6 +17,7 @@ Version 0.6:
|
|||
* Dwarven Doors
|
||||
* Mountain Pass
|
||||
* Valley of Death
|
||||
* support for multiple campaigns
|
||||
* new campaign started: 'Hordes of the Undead'
|
||||
* multiplayer improvements:
|
||||
* show minimap when selecting map for new game
|
||||
|
@ -47,10 +48,12 @@ Version 0.6:
|
|||
* Elvish Scout
|
||||
* Pikeman
|
||||
* Dwarvish Steelclad
|
||||
* undead are now immune to poinson and plague
|
||||
* Konrad now starts as Fighter, which is 1st level unit
|
||||
* undead are now immune to poison and plague
|
||||
* reduced movement for Elvish Lord
|
||||
* reduced cost of Mage
|
||||
* changed Mage attack to fire based
|
||||
* 'Mage of Light' has now both cure and illumination
|
||||
* changed Shaman slowing attack to 3-2 from 4-1, and reduced cost from 21 to 18
|
||||
* changed 'Red Mage' to neutral alignment
|
||||
* removed 'Elvish Outrider' as evolution from Horseman
|
||||
|
@ -61,8 +64,8 @@ Version 0.6:
|
|||
* 'Blood Bat' unit description clarified
|
||||
* Halberdier changed to 3rd level unit
|
||||
* Spearman now advances to Pikeman
|
||||
* Fire resistance added to 'Red Mage' branch units
|
||||
* Holy resistance added to Holy units.
|
||||
* Increased fire resistance for 'Red Mage' branch units
|
||||
* Increased holy resistance made higher for Holy units.
|
||||
* auto-naming (currently elves and humans only) of units and renaming of units
|
||||
* units now have races defined in cfg-files
|
||||
* more and improved unit graphics and animations
|
||||
|
@ -86,6 +89,7 @@ Version 0.6:
|
|||
* added in support for some special effects: flashing and scrolling/tremors
|
||||
* added coding support for displaying different terrain images (particularly useful for villages) at different times of the day
|
||||
* fixed minor bugs in unit configuration files for Elvish Sharpshooter and Fencer
|
||||
* fixed problem where 'goto numbers' can overwrite part of the right panel
|
||||
* footsteps disappear as you walk over them
|
||||
* added engine support for weapons that can reach multiple hexes
|
||||
* added some utility macros to WML
|
||||
|
@ -122,6 +126,7 @@ Version 0.6:
|
|||
* fixed tool tips to work again
|
||||
* fix hitpoint bar problem on MacOSX
|
||||
* added diagnostic to attack calculations
|
||||
* added error logging and correction for combat related syncing errors
|
||||
* client_type=ai in preferences-file make player join networked multiplayer games as AI player
|
||||
* added some comments to code
|
||||
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -1337,7 +1337,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||
|
||||
PACKAGE=wesnoth
|
||||
MAJOR_VERSION="0"
|
||||
MINOR_VERSION="6RC2"
|
||||
MINOR_VERSION="6RC3"
|
||||
MICRO_VERSION=""
|
||||
|
||||
if test "x$MICRO_VERSION" = "x"; then
|
||||
|
|
|
@ -6,7 +6,7 @@ AC_INIT(wesnoth, 0.5, davidnwhite@optusnet.com.au, Battle for Wesnoth)
|
|||
AC_REVISION($Version: 0.5$)
|
||||
PACKAGE=wesnoth
|
||||
MAJOR_VERSION="0"
|
||||
MINOR_VERSION="6RC2"
|
||||
MINOR_VERSION="6RC3"
|
||||
MICRO_VERSION=""
|
||||
|
||||
if test "x$MICRO_VERSION" = "x"; then
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
{STORM_TRIDENT 10 5}
|
||||
|
||||
[side]
|
||||
type=Commander
|
||||
type=Fighter
|
||||
description=Konrad
|
||||
side=1
|
||||
canrecruit=1
|
||||
|
|
|
@ -25,7 +25,6 @@ Defeat
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Thief,Merman
|
||||
enemy=2,3
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
objectives="
|
||||
Victory:
|
||||
@Defeat both enemy leaders
|
||||
@Defeat at least one enemy leader, and resist until time expires
|
||||
Defeat:
|
||||
#Death of Konrad
|
||||
#Turns run out"
|
||||
|
@ -499,12 +500,18 @@ The main cage where they keep most of the mermen is in the south-east!"
|
|||
[/message]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=victory
|
||||
#the ship they came on.
|
||||
[item]
|
||||
x=30
|
||||
y=7
|
||||
image=galleon.png
|
||||
[/item]
|
||||
|
||||
#define BAY_OF_PEARLS_VICTORY
|
||||
[message]
|
||||
id=msg3_16
|
||||
description=Konrad
|
||||
message=At last, we have freed the mermen. Go back to the ocean and leave in peace.
|
||||
message=At last, we have freed the mermen. Go back to the ocean and live in peace.
|
||||
[/message]
|
||||
[role]
|
||||
type=Merman Lord,Merman
|
||||
|
@ -545,7 +552,7 @@ The main cage where they keep most of the mermen is in the south-east!"
|
|||
[message]
|
||||
id=msg3_22
|
||||
description=Konrad
|
||||
message=Oh no! What should we do?
|
||||
message=Oh no! What shall we do?
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
|
@ -573,7 +580,7 @@ The main cage where they keep most of the mermen is in the south-east!"
|
|||
[/message]
|
||||
|
||||
[role]
|
||||
type=Elvish Champion,Elvish Marshal,Elvish Captain,Elvish Hero,Knight,Elvish Outrider,Paladin,Mage,White Mage,Red Mage
|
||||
type=Elvish Champion,Elvish Marshal,Elvish Captain,Elvish Hero,Knight,Elvish Outrider,Paladin,Mage,White Mage,Red Mage,Elvish Fighter,Elvish Archer,Elvish Shaman,Horseman
|
||||
role=Supporter
|
||||
[/role]
|
||||
[message]
|
||||
|
@ -587,18 +594,215 @@ The main cage where they keep most of the mermen is in the south-east!"
|
|||
message=You will prevail. I have faith in you. Travel north. Elensefar is but three days travel if you make haste.
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_29
|
||||
id=msg3_29a
|
||||
description=Konrad
|
||||
message=Very well. Until we meet again, my dear friend!
|
||||
message=Very well. But how do I get to Elensefar?
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_30
|
||||
id=msg3_30a
|
||||
description=Delfador
|
||||
message=Farewell, prince.
|
||||
message=It is north-west of here, but a few leagues inland from the coast. There are two ways you may get there, by ship, or by land. Each way has its own dangers and perils. You must choose how you wish to get there.
|
||||
[option]
|
||||
id=msg3_30_optiona
|
||||
message="Ships? Ugh! I have been sea sick for the last time. We shall walk!"
|
||||
[command]
|
||||
[message]
|
||||
id=msg3_30_farewell
|
||||
description=Delfador
|
||||
message=Safe journey to you, Konrad. Until we meet again!
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
[kill]
|
||||
description=Delfador
|
||||
[/kill]
|
||||
[/command]
|
||||
[command]
|
||||
[endlevel]
|
||||
result=victory
|
||||
next_scenario=Muff_Malals_Peninsula
|
||||
bonus=yes
|
||||
[/endlevel]
|
||||
[/command]
|
||||
|
||||
[/option]
|
||||
[option]
|
||||
id=msg3_30_optionb
|
||||
message="At least going by ship we may get a little rest for ourselves. By sea it is!"
|
||||
[command]
|
||||
[message]
|
||||
id=msg3_30_farewella
|
||||
description=Delfador
|
||||
message=Safe voyage to you then, Konrad. May the weather be fair.
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
[kill]
|
||||
description=Delfador
|
||||
[/kill]
|
||||
[/command]
|
||||
[command]
|
||||
[endlevel]
|
||||
result=victory
|
||||
next_scenario=Isle_of_the_Damned
|
||||
bonus=yes
|
||||
[/endlevel]
|
||||
[/command]
|
||||
[/option]
|
||||
[/message]
|
||||
[kill]
|
||||
description=Delfador
|
||||
[/kill]
|
||||
#enddef
|
||||
|
||||
#track which enemy leaders are dead
|
||||
[event]
|
||||
name=die
|
||||
[filter]
|
||||
description=Dwaba-Kukai
|
||||
[/filter]
|
||||
[if]
|
||||
[variable]
|
||||
name=land_orc_dead
|
||||
equals=yes
|
||||
[/variable]
|
||||
[then]
|
||||
{BAY_OF_PEARLS_VICTORY}
|
||||
[/then]
|
||||
[else]
|
||||
[set_variable]
|
||||
name=sea_orc_dead
|
||||
value=yes
|
||||
[/set_variable]
|
||||
[/else]
|
||||
[/if]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=die
|
||||
[filter]
|
||||
description=Managa'Gwin
|
||||
[/filter]
|
||||
[if]
|
||||
[variable]
|
||||
name=sea_orc_dead
|
||||
equals=yes
|
||||
[/variable]
|
||||
[then]
|
||||
{BAY_OF_PEARLS_VICTORY}
|
||||
[/then]
|
||||
[else]
|
||||
[set_variable]
|
||||
name=land_orc_dead
|
||||
value=yes
|
||||
[/set_variable]
|
||||
[/else]
|
||||
[/if]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=time over
|
||||
[command]
|
||||
[unit]
|
||||
x=18
|
||||
y=1
|
||||
description=Delfador
|
||||
type=Elder Mage
|
||||
[/unit]
|
||||
[/command]
|
||||
|
||||
[command]
|
||||
|
||||
#if neither of the enemies are dead, automatically lose
|
||||
[if]
|
||||
[variable]
|
||||
name=sea_orc_dead
|
||||
not_equals=yes
|
||||
[/variable]
|
||||
[variable]
|
||||
name=land_orc_dead
|
||||
not_equals=yes
|
||||
[/variable]
|
||||
|
||||
[then]
|
||||
[message]
|
||||
id=msg3_31
|
||||
description=Delfador
|
||||
message="Have you not been able to defeat our foes in all these days? They have summoned reinforcements. Surely now our doom is upon us!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
result=defeat
|
||||
[/endlevel]
|
||||
[/then]
|
||||
|
||||
#if we have killed at least one Orcish leader, we
|
||||
#go on to the next scenario
|
||||
[else]
|
||||
[command]
|
||||
[message]
|
||||
id=msg3_32
|
||||
description=Delfador
|
||||
message="Konrad! We cannot spend anymore time here. Though it would be good to defeat the Orcs and free all we can, more urgent business calls us!"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_33
|
||||
description=Konrad
|
||||
message=Delfador, thank goodness you have survived! This has been a tough battle, but why can we not finish it? Why must we leave?
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_34
|
||||
description=Delfador
|
||||
message=I bear ill tidings: Asheviere has attacked the city of Elensefar, breaking the treaty between Wesnoth and Elensefar. You must lead our men to the city, to help defend it -- or to recapture it if it falls before you arrive.
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_35
|
||||
description=Konrad
|
||||
message=I must do this? But you are coming with me, aren't you, Delfador?
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_36
|
||||
description=Delfador
|
||||
message=I am afraid not Konrad. I have found some important documents that need seeing to. I must ride at once to make council with the Elves. I will meet you in Elensefar, after you have secured it.
|
||||
[/message]
|
||||
[message]
|
||||
id=msg3_37
|
||||
description=Konrad
|
||||
message=I fear I will struggle to do this on my own, but what must be must be. How do I get to Elensefar?
|
||||
[/message]
|
||||
[/command]
|
||||
|
||||
#if we killed the orc at sea, we travel by ship
|
||||
#if we killed the orc on land, we travel by land
|
||||
[command]
|
||||
[if]
|
||||
[variable]
|
||||
name=sea_orc_dead
|
||||
equals=yes
|
||||
[/variable]
|
||||
[then]
|
||||
[message]
|
||||
id=msg3_38
|
||||
description=Delfador
|
||||
message="Since you have broken the Orc's hegemony over the seas, going by ship would be safest. Sail along the coast, and you can land mere miles from Elensefar. Make haste!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
result=victory
|
||||
next_scenario=Isle_of_the_Damned
|
||||
[/endlevel]
|
||||
[/then]
|
||||
[else]
|
||||
[message]
|
||||
id=msg3_39
|
||||
description=Delfador
|
||||
message="With the Orcs controlling the seas, going by ship would not be safe. Travel by land, Elensefar is only six day's march up the coast. Make haste!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
result=victory
|
||||
next_scenario=Muff_Malals_Peninsula
|
||||
[/endlevel]
|
||||
[/else]
|
||||
[/if]
|
||||
[/command]
|
||||
[/else]
|
||||
[/if]
|
||||
[/command]
|
||||
[/event]
|
||||
[/scenario]
|
||||
|
||||
|
|
|
@ -17,11 +17,7 @@
|
|||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=187
|
||||
y=187
|
||||
[/dot]
|
||||
{CROSS 378 140}
|
||||
[/bigmap]
|
||||
|
||||
objectives="
|
||||
|
@ -74,7 +70,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
enemy=2,3,4
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ Defeat:
|
|||
[/bigmap]
|
||||
|
||||
[side]
|
||||
type=Commander
|
||||
type=Fighter
|
||||
description=Konrad
|
||||
side=1
|
||||
canrecruit=1
|
||||
|
@ -62,11 +62,11 @@ Defeat:
|
|||
[target]
|
||||
description=Delfador
|
||||
value=100
|
||||
[end]
|
||||
[/target]
|
||||
[target]
|
||||
description=Konrad
|
||||
value=100
|
||||
[end]
|
||||
[/target]
|
||||
#enddef
|
||||
#else
|
||||
#define HIGH_PRIORITY_TARGETS
|
||||
|
@ -205,7 +205,7 @@ Defeat:
|
|||
id=msg1_9hard
|
||||
description=Knafa-Tan
|
||||
message="Remember, it is rumored that the filthy mage, and one that he protects is in these parts. They are the ones we want!"
|
||||
[end]
|
||||
[/message]
|
||||
#else
|
||||
[message]
|
||||
id=msg1_9
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=187
|
||||
y=187
|
||||
[/dot]
|
||||
{DOT 305 202}
|
||||
{DOT 313 195}
|
||||
{DOT 321 188}
|
||||
{CROSS 321 182}
|
||||
[/bigmap]
|
||||
|
||||
objectives="
|
||||
|
@ -38,7 +37,7 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
recruit=Gryphon Rider
|
||||
enemy=2,3
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@ Defeat:
|
|||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
{DOT 262 225}
|
||||
{DOT 272 214}
|
||||
{DOT 288 207}
|
||||
{CROSS 298 208}
|
||||
type=cross
|
||||
x=187
|
||||
y=187
|
||||
|
@ -63,7 +67,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Merman,Thief
|
||||
enemy=2,3
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider,Dwarvish Fighter,Dwarvish Thunderer
|
||||
enemy=3
|
||||
shroud=yes
|
||||
[/side]
|
||||
|
|
170
data/scenarios/Isle_of_the_Damned.cfg
Normal file
170
data/scenarios/Isle_of_the_Damned.cfg
Normal file
|
@ -0,0 +1,170 @@
|
|||
[scenario]
|
||||
{DAWN}
|
||||
{MORNING}
|
||||
{AFTERNOON}
|
||||
{DUSK}
|
||||
{FIRST_WATCH}
|
||||
{SECOND_WATCH}
|
||||
|
||||
id=Isle_of_the_Damned
|
||||
next_scenario=The_Siege_of_Elensefar
|
||||
name=Isle of the Damned
|
||||
map=isle_damned
|
||||
turns=24
|
||||
|
||||
music="wesnoth-3.ogg"
|
||||
|
||||
objectives="
|
||||
Victory:
|
||||
@Defeat both enemy leaders
|
||||
@Resist until the end of the turns
|
||||
Defeat:
|
||||
#Death of Konrad"
|
||||
|
||||
disallow_recall=yes
|
||||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
{DOT 162 367}
|
||||
{DOT 158 372}
|
||||
{DOT 151 379}
|
||||
{DOT 137 385}
|
||||
{DOT 122 383}
|
||||
{DOT 109 377}
|
||||
{DOT 99 369}
|
||||
{DOT 94 374}
|
||||
{CROSS 93 386}
|
||||
[/bigmap]
|
||||
|
||||
[side]
|
||||
description=Konrad
|
||||
type=Commander
|
||||
side=1
|
||||
canrecruit=1
|
||||
enemy=2,3
|
||||
controller=human
|
||||
[unit]
|
||||
description=Kalba
|
||||
type=Merman
|
||||
side=1
|
||||
x=25
|
||||
y=10
|
||||
[/unit]
|
||||
[unit]
|
||||
description=Gnaba
|
||||
type=Merman
|
||||
side=1
|
||||
x=29
|
||||
y=12
|
||||
[/unit]
|
||||
[/side]
|
||||
[side]
|
||||
description=Haf-Mal
|
||||
type=Lich
|
||||
side=2
|
||||
canrecruit=1
|
||||
enemy=1
|
||||
recruit=Skeleton,Vampire Bat,Ghost,Dark Adept,Chocobone
|
||||
recruitment_pattern=scout,scout,fighter
|
||||
{GOLD 80 140 200}
|
||||
[/side]
|
||||
[side]
|
||||
description=Jarmal-Gorg
|
||||
type=Lich
|
||||
side=3
|
||||
canrecruit=1
|
||||
enemy=1
|
||||
recruit=Skeleton,Skeleton Archer,Walking Corpse,Vampire Bat,Ghost,Dark Adept
|
||||
{GOLD 80 140 200}
|
||||
[/side]
|
||||
|
||||
[story]
|
||||
[part]
|
||||
id=isledamn_1
|
||||
story="But the voyage did not go as smoothly as had been hoped. A storm lashed down on the ship, all hands were on deck, trying desperately to save the ship. As Konrad attempted to secure the mast, a sudden gust of wind flung him overboard..."
|
||||
image="misc/map.png"
|
||||
[/part]
|
||||
[part]
|
||||
id=isledamn_2
|
||||
story="The mermen saved Konrad from the seas, but were not able to get him back to the ship. Instead, they had to resort to taking him to a nearby island..."
|
||||
image="misc/map.png"
|
||||
[/part]
|
||||
[/story]
|
||||
|
||||
[event]
|
||||
name=start
|
||||
[message]
|
||||
description=Konrad
|
||||
id=isledamn_3
|
||||
message="Whew, I survived. But now where am I? Is this island inhabited?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Kalba
|
||||
id=isledamn_4
|
||||
message="There have been ill tidings about this island, my lord. It is said that the fiends of the undead have overtaken it, and it has fallen into ugly wasteland."
|
||||
[/message]
|
||||
[message]
|
||||
description=Konrad
|
||||
id=isledamn_5
|
||||
message="Let us hope these rumors are not true! I have none of my men with me! How would I defend myself?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Kalba
|
||||
id=isledamn_6
|
||||
message="There are still some Elves on this island, my lord, perhaps if you recruit some of them to help you, we might have some hope of holding off the undead hordes!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
#define ISLE_GALLEON_ARRIVE
|
||||
[command]
|
||||
[move_unit_fake]
|
||||
type=Galleon
|
||||
x=23,23,23,23,23,24
|
||||
y=1,2,3,4,5,5
|
||||
[/move_unit_fake]
|
||||
[/command]
|
||||
[command]
|
||||
[item]
|
||||
x=24
|
||||
y=5
|
||||
image=galleon.png
|
||||
[/item]
|
||||
[/command]
|
||||
#enddef
|
||||
|
||||
[event]
|
||||
name=enemies defeated
|
||||
[command]
|
||||
[message]
|
||||
description=Konrad
|
||||
message="We have wrested control of the island from the evil undead! Now all we have to do is wait for the ship to arrive, so we can make our way to Elensefar!"
|
||||
[/message]
|
||||
[/command]
|
||||
|
||||
{ISLE_GALLEON_ARRIVE}
|
||||
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=time over
|
||||
{ISLE_GALLEON_ARRIVE}
|
||||
[command]
|
||||
[message]
|
||||
speaker=narrator
|
||||
image=elvish-fighter.png
|
||||
message="Thank goodness we have found you, sir! Come aboard quickly, we shall take you away from this horrible island!"
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
[message]
|
||||
description=Konrad
|
||||
message="It is a shame complete victory could not be ours, but thank goodness I am rescued! On to Elensefar!"
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
[endlevel]
|
||||
result=victory
|
||||
[/endlevel]
|
||||
[/command]
|
||||
[/event]
|
||||
[/scenario]
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=187
|
||||
y=187
|
||||
[/dot]
|
||||
{DOT 354 167}
|
||||
{DOT 355 157}
|
||||
{CROSS 356 147}
|
||||
[/bigmap]
|
||||
|
||||
objectives="
|
||||
|
@ -38,7 +36,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
enemy=2,3
|
||||
fog=yes
|
||||
[/side]
|
||||
|
@ -61,15 +58,8 @@ Defeat:
|
|||
recruitment_pattern=fighter
|
||||
villages_per_scout=0
|
||||
|
||||
#ifdef EASY
|
||||
gold=150
|
||||
#endif
|
||||
#ifdef NORMAL
|
||||
gold=200
|
||||
#endif
|
||||
#ifdef HARD
|
||||
gold=280
|
||||
#endif
|
||||
{GOLD 150 200 280}
|
||||
|
||||
enemy=1
|
||||
[/side]
|
||||
|
||||
|
@ -87,18 +77,8 @@ Defeat:
|
|||
#endif
|
||||
recruitment_pattern=fighter,scout,scout,mixed fighter
|
||||
villages_per_scout=0
|
||||
#ifdef EASY
|
||||
gold=200
|
||||
income=20
|
||||
#endif
|
||||
#ifdef NORMAL
|
||||
gold=250
|
||||
income=30
|
||||
#endif
|
||||
#ifdef HARD
|
||||
gold=350
|
||||
income=50
|
||||
#endif
|
||||
{GOLD 150 250 350}
|
||||
{INCOME 15 30 50}
|
||||
enemy=1
|
||||
village_value=0
|
||||
leader_value=10
|
||||
|
|
|
@ -27,7 +27,7 @@ Defeat:
|
|||
image=misc/map.png
|
||||
{DOT 164 348}
|
||||
{DOT 158 340}
|
||||
{DOT 142 355}
|
||||
{DOT 142 338}
|
||||
{DOT 127 340}
|
||||
{CROSS 122 331}
|
||||
[/bigmap]
|
||||
|
@ -224,6 +224,11 @@ Defeat:
|
|||
[kill]
|
||||
description=Moremirmu
|
||||
[/kill]
|
||||
[message]
|
||||
id=msg4_12b
|
||||
description=Konrad
|
||||
message="Victory is ours! Let us just hope that this delay will not hamper our quest to save Elensefar. We must move onward with haste!"
|
||||
[/message]
|
||||
[/event]
|
||||
[event]
|
||||
name=die
|
||||
|
|
|
@ -26,11 +26,9 @@ Defeat:
|
|||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=77
|
||||
y=235
|
||||
[/dot]
|
||||
{DOT 336 180}
|
||||
{DOT 344 174}
|
||||
{CROSS 354 167}
|
||||
[/bigmap]
|
||||
|
||||
[side]
|
||||
|
@ -41,7 +39,6 @@ Defeat:
|
|||
experience=0
|
||||
side=1
|
||||
canrecruit=1
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
enemy=2,3
|
||||
controller=human
|
||||
[/side]
|
||||
|
|
|
@ -33,7 +33,6 @@ Defeat
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider
|
||||
enemy=2
|
||||
shroud=yes
|
||||
[/side]
|
||||
|
|
|
@ -53,8 +53,7 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief
|
||||
enemy=2
|
||||
enemy=2
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
|
|
|
@ -34,7 +34,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider,Dwarvish Fighter,Dwarvish Thunderer
|
||||
enemy=2,3,4,5,6
|
||||
shroud=yes
|
||||
[/side]
|
||||
|
@ -48,20 +47,8 @@ Defeat:
|
|||
recruit=Goblin Knight,Wolf Rider,Troll,Orcish Warrior,Orcish Crossbow
|
||||
enemy=1
|
||||
|
||||
#ifdef EASY
|
||||
gold=300
|
||||
income=10
|
||||
#endif
|
||||
|
||||
#ifdef MEDIUM
|
||||
gold=400
|
||||
income=20
|
||||
#endif
|
||||
|
||||
#ifdef HARD
|
||||
gold=550
|
||||
income=30
|
||||
#endif
|
||||
{GOLD 150 300 400}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
[side]
|
||||
type=Troll Warrior
|
||||
|
@ -72,21 +59,8 @@ Defeat:
|
|||
recruitment_pattern=fighter
|
||||
recruit=Troll,Troll Warrior,Ogre
|
||||
enemy=1
|
||||
|
||||
#ifdef EASY
|
||||
gold=300
|
||||
income=10
|
||||
#endif
|
||||
|
||||
#ifdef MEDIUM
|
||||
gold=400
|
||||
income=20
|
||||
#endif
|
||||
|
||||
#ifdef HARD
|
||||
gold=550
|
||||
income=30
|
||||
#endif
|
||||
{GOLD 150 300 400}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
|
@ -99,20 +73,8 @@ Defeat:
|
|||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
enemy=1
|
||||
|
||||
#ifdef EASY
|
||||
gold=200
|
||||
income=10
|
||||
#endif
|
||||
|
||||
#ifdef MEDIUM
|
||||
gold=300
|
||||
income=20
|
||||
#endif
|
||||
|
||||
#ifdef HARD
|
||||
gold=450
|
||||
income=30
|
||||
#endif
|
||||
{GOLD 150 230 350}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
|
@ -124,21 +86,8 @@ Defeat:
|
|||
recruitment_pattern=fighter,fighter,scout
|
||||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
enemy=1
|
||||
|
||||
#ifdef EASY
|
||||
gold=200
|
||||
income=15
|
||||
#endif
|
||||
|
||||
#ifdef MEDIUM
|
||||
gold=300
|
||||
income=20
|
||||
#endif
|
||||
|
||||
#ifdef HARD
|
||||
gold=450
|
||||
income=30
|
||||
#endif
|
||||
{GOLD 150 230 350}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
|
||||
#dummy enemy that forces finding the Sceptre
|
||||
|
|
|
@ -123,7 +123,7 @@ Defeat:
|
|||
[/message]
|
||||
[message]
|
||||
id=msg5_4
|
||||
description=Advisor
|
||||
role=Advisor
|
||||
message=There are so many of them. This will not be easy! And look to the south, it seems that the undead are allied with the Orcs!
|
||||
[/message]
|
||||
[message]
|
||||
|
@ -139,7 +139,7 @@ Defeat:
|
|||
[/event]
|
||||
|
||||
[event]
|
||||
name=turn 6
|
||||
name=turn 5
|
||||
[unit]
|
||||
description=Reglok
|
||||
type=Thief
|
||||
|
@ -178,7 +178,7 @@ Defeat:
|
|||
[/message]
|
||||
[message]
|
||||
id=msg5_10
|
||||
description=Advisor
|
||||
role=Advisor
|
||||
message=Thieves hmmm? Who says we can trust such as you?
|
||||
[/message]
|
||||
[message]
|
||||
|
@ -187,9 +187,41 @@ Defeat:
|
|||
message=We would understand if you don't trust us, of course, but it is in both our best interests to rid the city of the Orcs!
|
||||
[/message]
|
||||
[message]
|
||||
id=msg5_12
|
||||
id=msg5_12a
|
||||
description=Konrad
|
||||
message=Very well, you may join us.
|
||||
message=Hmm...I have to consider this...
|
||||
[option]
|
||||
id=accept_thieves
|
||||
message="Very well. You may join us."
|
||||
[command]
|
||||
[message]
|
||||
id=msg5_13
|
||||
description=Gamlel
|
||||
message=We will serve you well, for we respect the help you are providing to our city. You shall find that there is honor, even among thieves.
|
||||
[/message]
|
||||
[set_variable]
|
||||
name=have_thieves
|
||||
value=yes
|
||||
[/set_variable]
|
||||
[can_recruit]
|
||||
type=Thief
|
||||
[/can_recruit]
|
||||
[/command]
|
||||
[/option]
|
||||
[option]
|
||||
id=reject_thieves
|
||||
message="We cannot trust your motives. We shall rescue the city on our own!"
|
||||
[command]
|
||||
[message]
|
||||
id=msg5_14
|
||||
description=Gamlel
|
||||
message="Very well, we shall begone then. You shall have to recapture the city without our help!"
|
||||
[/message]
|
||||
[kill]
|
||||
type=Thief
|
||||
[/kill]
|
||||
[/command]
|
||||
[/option]
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ Defeat
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Thief,Merman
|
||||
enemy=2,3
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ Defeat
|
|||
canrecruit=1
|
||||
controller=human
|
||||
hitpoints=80
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Thief,Merman
|
||||
enemy=2,3,4,5,6
|
||||
[/side]
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief,Gryphon Rider,Dwarvish Fighter,Dwarvish Thunderer
|
||||
recruit=Dwarvish Fighter,Dwarvish Thunderer
|
||||
enemy=3,4
|
||||
shroud=yes
|
||||
[/side]
|
||||
|
|
|
@ -25,11 +25,10 @@ Defeat:
|
|||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
[dot]
|
||||
type=cross
|
||||
x=207
|
||||
y=147
|
||||
[/dot]
|
||||
{DOT 250 255}
|
||||
{DOT 251 246}
|
||||
{DOT 253 239}
|
||||
{CROSS 253 231}
|
||||
[/bigmap]
|
||||
|
||||
[side]
|
||||
|
@ -38,7 +37,6 @@ Defeat:
|
|||
side=1
|
||||
canrecruit=1
|
||||
controller=human
|
||||
recruit=Elvish Scout,Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman,Merman,Thief
|
||||
recruitment_pattern=scout,fighter,archer
|
||||
aggression=-0.5
|
||||
village_value=1.0
|
||||
|
|
|
@ -20,7 +20,7 @@ Defeat:
|
|||
|
||||
[side]
|
||||
race=Elves
|
||||
type=Commander
|
||||
type=Fighter
|
||||
description=Konrad
|
||||
experience=0
|
||||
side=1
|
||||
|
|
|
@ -7,7 +7,7 @@ hitpoints=45
|
|||
ability=leadership
|
||||
movement_type=smallfoot
|
||||
movement=6
|
||||
experience=80
|
||||
experience=60
|
||||
level=2
|
||||
alignment=lawful
|
||||
advanceto=Lord
|
||||
|
@ -29,15 +29,15 @@ get_hit_sound=groan.wav
|
|||
name=sword
|
||||
type=blade
|
||||
range=short
|
||||
damage=6
|
||||
damage=8
|
||||
number=4
|
||||
[frame]
|
||||
begin=-350
|
||||
end=-300
|
||||
begin=-250
|
||||
end=-200
|
||||
image=konrad-commander.png
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-300
|
||||
begin=-200
|
||||
end=-100
|
||||
image="konrad-commander-attack1.png"
|
||||
[/frame]
|
||||
|
@ -66,7 +66,7 @@ get_hit_sound=groan.wav
|
|||
name=bow
|
||||
type=pierce
|
||||
range=long
|
||||
damage=3
|
||||
damage=6
|
||||
number=3
|
||||
[sound]
|
||||
time=-100
|
||||
|
|
39
data/units/Fighter.cfg
Normal file
39
data/units/Fighter.cfg
Normal file
|
@ -0,0 +1,39 @@
|
|||
[unit]
|
||||
name=Fighter
|
||||
race=human
|
||||
image=konrad-young.png
|
||||
profile=misc/konrad.png
|
||||
hitpoints=32
|
||||
movement_type=smallfoot
|
||||
movement=6
|
||||
experience=28
|
||||
level=1
|
||||
alignment=lawful
|
||||
advanceto=Commander
|
||||
cost=100
|
||||
usage=mixed fighter
|
||||
unit_description="The fighter is skilled with use of the sword in battle. Young and brash, he is vulnerable to attack from enemies. However he has the potential to one day become a great warrior"
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
name=sword
|
||||
type=blade
|
||||
range=short
|
||||
damage=6
|
||||
number=3
|
||||
[frame]
|
||||
begin=-250
|
||||
end=-100
|
||||
image=konrad-young.png
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="konrad-young-attack.png"
|
||||
[/frame]
|
||||
|
||||
[sound]
|
||||
time=-250
|
||||
sound=sword-swish.wav
|
||||
[/sound]
|
||||
[/attack]
|
||||
[/unit]
|
|
@ -12,7 +12,7 @@ alignment=chaotic
|
|||
advanceto=null
|
||||
cost=22
|
||||
usage=scout
|
||||
unit_desc="Some goblins train their wolves to dont fear file. Wielding tochs and nets goblin pillager bring havok to his enemies."
|
||||
unit_description="Some goblins train their wolves to overcome their fear of fire. Wielding torches and nets, Goblin Pillagers bring havoc to their enemies."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
name=torch
|
||||
|
|
|
@ -3,7 +3,7 @@ name=Lord
|
|||
race=human
|
||||
image=konrad-lord.png
|
||||
profile=misc/konrad.png
|
||||
hitpoints=65
|
||||
hitpoints=68
|
||||
ability=leadership
|
||||
movement_type=smallfoot
|
||||
movement=6
|
||||
|
@ -19,7 +19,7 @@ get_hit_sound=groan.wav
|
|||
name=sword
|
||||
type=blade
|
||||
range=short
|
||||
damage=11
|
||||
damage=14
|
||||
number=4
|
||||
[/attack]
|
||||
[attack]
|
||||
|
|
|
@ -20,5 +20,10 @@ usage=fighter
|
|||
range=short
|
||||
damage=14
|
||||
number=2
|
||||
[frame]
|
||||
begin=-100
|
||||
end=100
|
||||
image=troll-grunt-attack.png
|
||||
[/frame]
|
||||
[/attack]
|
||||
[/unit]
|
||||
|
|
BIN
images/troll-grunt-attack.png
Normal file
BIN
images/troll-grunt-attack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 707 B |
129
src/actions.cpp
129
src/actions.cpp
|
@ -341,15 +341,72 @@ void attack(display& gui, const gamemap& map,
|
|||
|
||||
while(stats.nattacks > 0 || stats.ndefends > 0) {
|
||||
if(stats.nattacks > 0) {
|
||||
const bool hits = (get_random()%100) < stats.chance_to_hit_defender;
|
||||
const bool dies = gui.unit_attack(attacker,defender,
|
||||
hits ? stats.damage_defender_takes : 0,
|
||||
a->second.attacks()[attack_with]);
|
||||
const int ran_num = get_random();
|
||||
bool hits = (ran_num%100) < stats.chance_to_hit_defender;
|
||||
|
||||
//make sure that if we're serializing a game here,
|
||||
//we got the same results as the game did originally
|
||||
const config* ran_results = get_random_results();
|
||||
if(ran_results != NULL) {
|
||||
const int results_chance = atoi((*ran_results)["chance"].c_str());
|
||||
const bool results_hits = (*ran_results)["hits"] == "yes";
|
||||
const int results_damage = atoi((*ran_results)["damage"].c_str());
|
||||
|
||||
if(results_chance != stats.chance_to_hit_defender) {
|
||||
std::cerr << "SYNC ERROR: In attack " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": chance to hit defender is inconsistent. Data source: "
|
||||
<< results_chance << "; Calculation: " << stats.chance_to_hit_defender
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
} else if(hits != results_hits) {
|
||||
std::cerr << "SYNC ERROR: In attack " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source says the hit was "
|
||||
<< (results_hits ? "successful" : "unsuccessful") << ", while in-game calculations say the hit was "
|
||||
<< (hits ? "successful" : "unsuccessful")
|
||||
<< " random number: " << ran_num << " = " << (ran_num%100) << "/" << results_chance
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
} else if(results_damage != stats.damage_defender_takes) {
|
||||
std::cerr << "SYNC ERROR: In attack " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source says the hit did "
|
||||
<< results_damage << " damage, while in-game calculations show the hit doing "
|
||||
<< stats.damage_defender_takes << " damage (over-riding game calculations with data source results)\n";
|
||||
stats.damage_defender_takes = results_damage;
|
||||
}
|
||||
}
|
||||
|
||||
bool dies = gui.unit_attack(attacker,defender,
|
||||
hits ? stats.damage_defender_takes : 0,
|
||||
a->second.attacks()[attack_with]);
|
||||
|
||||
if(ran_results == NULL) {
|
||||
config cfg;
|
||||
cfg["hits"] = (hits ? "yes" : "no");
|
||||
cfg["dies"] = (dies ? "yes" : "no");
|
||||
char buf[50];
|
||||
sprintf(buf,"%d",stats.damage_defender_takes);
|
||||
cfg["damage"] = buf;
|
||||
sprintf(buf,"%d",stats.chance_to_hit_defender);
|
||||
cfg["chance"] = buf;
|
||||
set_random_results(cfg);
|
||||
} else {
|
||||
const bool results_dies = (*ran_results)["dies"] == "yes";
|
||||
if(results_dies != dies) {
|
||||
std::cerr << "SYNC ERROR: In attack" << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source the unit "
|
||||
<< (results_dies ? "perished" : "survived") << " while in-game calculations show the unit "
|
||||
<< (dies ? "perished" : "survived") << " (over-riding game calculations with data source results)\n";
|
||||
dies = results_dies;
|
||||
}
|
||||
}
|
||||
|
||||
if(dies) {
|
||||
attackerxp = 8*d->second.type().level();
|
||||
if(d->second.type().level() == 0)
|
||||
attackerxp = 4;
|
||||
|
||||
a->second.get_experience(attackerxp);
|
||||
attackerxp = 0;
|
||||
defenderxp = 0;
|
||||
|
||||
gamemap::location loc = d->first;
|
||||
|
@ -397,16 +454,72 @@ void attack(display& gui, const gamemap& map,
|
|||
}
|
||||
|
||||
if(stats.ndefends > 0) {
|
||||
const bool hits = (get_random()%100) < stats.chance_to_hit_attacker;
|
||||
const bool dies = gui.unit_attack(defender,attacker,
|
||||
const int ran_num = get_random();
|
||||
bool hits = (ran_num%100) < stats.chance_to_hit_attacker;
|
||||
|
||||
//make sure that if we're serializing a game here,
|
||||
//we got the same results as the game did originally
|
||||
const config* ran_results = get_random_results();
|
||||
if(ran_results != NULL) {
|
||||
const int results_chance = atoi((*ran_results)["chance"].c_str());
|
||||
const bool results_hits = (*ran_results)["hits"] == "yes";
|
||||
const int results_damage = atoi((*ran_results)["damage"].c_str());
|
||||
|
||||
if(results_chance != stats.chance_to_hit_attacker) {
|
||||
std::cerr << "SYNC ERROR: In defend " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": chance to hit attacker is inconsistent. Data source: "
|
||||
<< results_chance << "; Calculation: " << stats.chance_to_hit_attacker
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
} else if(hits != results_hits) {
|
||||
std::cerr << "SYNC ERROR: In defend " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source says the hit was "
|
||||
<< (results_hits ? "successful" : "unsuccessful") << ", while in-game calculations say the hit was "
|
||||
<< (hits ? "successful" : "unsuccessful")
|
||||
<< " random number: " << ran_num << " = " << (ran_num%100) << "/" << results_chance
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
} else if(results_damage != stats.damage_attacker_takes) {
|
||||
std::cerr << "SYNC ERROR: In defend " << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source says the hit did "
|
||||
<< results_damage << " damage, while in-game calculations show the hit doing "
|
||||
<< stats.damage_attacker_takes << " damage (over-riding game calculations with data source results)\n";
|
||||
stats.damage_attacker_takes = results_damage;
|
||||
}
|
||||
}
|
||||
|
||||
bool dies = gui.unit_attack(defender,attacker,
|
||||
hits ? stats.damage_attacker_takes : 0,
|
||||
d->second.attacks()[stats.defend_with]);
|
||||
|
||||
if(ran_results == NULL) {
|
||||
config cfg;
|
||||
cfg["hits"] = (hits ? "yes" : "no");
|
||||
cfg["dies"] = (dies ? "yes" : "no");
|
||||
char buf[50];
|
||||
sprintf(buf,"%d",stats.damage_attacker_takes);
|
||||
cfg["damage"] = buf;
|
||||
sprintf(buf,"%d",stats.chance_to_hit_attacker);
|
||||
cfg["chance"] = buf;
|
||||
set_random_results(cfg);
|
||||
} else {
|
||||
const bool results_dies = (*ran_results)["dies"] == "yes";
|
||||
if(results_dies != dies) {
|
||||
std::cerr << "SYNC ERROR: In defend" << a->second.type().name() << " vs "
|
||||
<< d->second.type().name() << ": the data source the unit "
|
||||
<< (results_dies ? "perished" : "survived") << " while in-game calculations show the unit "
|
||||
<< (dies ? "perished" : "survived") << " (over-riding game calculations with data source results)\n";
|
||||
dies = results_dies;
|
||||
}
|
||||
}
|
||||
|
||||
if(dies) {
|
||||
defenderxp = 8*a->second.type().level();
|
||||
if(a->second.type().level() == 0)
|
||||
defenderxp = 4;
|
||||
|
||||
d->second.get_experience(defenderxp);
|
||||
defenderxp = 0;
|
||||
attackerxp = 0;
|
||||
|
||||
gamemap::location loc = a->first;
|
||||
|
@ -742,6 +855,10 @@ void check_victory(std::map<gamemap::location,unit>& units,
|
|||
}
|
||||
|
||||
if(found_enemies == false) {
|
||||
if(found_human) {
|
||||
game_events::fire("enemies defeated");
|
||||
}
|
||||
|
||||
throw end_level_exception(found_human ? VICTORY : DEFEAT);
|
||||
}
|
||||
|
||||
|
|
|
@ -572,6 +572,17 @@ config::const_child_itors config::child_range(const std::string& key) const
|
|||
}
|
||||
}
|
||||
|
||||
const config::child_list& config::get_children(const std::string& key) const
|
||||
{
|
||||
const child_map::const_iterator i = children.find(key);
|
||||
if(i != children.end()) {
|
||||
return i->second;
|
||||
} else {
|
||||
static const child_list dummy;
|
||||
return dummy;
|
||||
}
|
||||
}
|
||||
|
||||
config* config::child(const std::string& key)
|
||||
{
|
||||
const child_map::const_iterator i = children.find(key);
|
||||
|
|
|
@ -107,6 +107,8 @@ struct config
|
|||
|
||||
child_itors child_range(const std::string& key);
|
||||
const_child_itors child_range(const std::string& key) const;
|
||||
|
||||
const child_list& get_children(const std::string& key) const;
|
||||
|
||||
config* child(const std::string& key);
|
||||
const config* child(const std::string& key) const;
|
||||
|
|
|
@ -1077,7 +1077,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image,
|
|||
|
||||
Pixel grid_colour = SDL_MapRGB(dst->format,0,0,0);
|
||||
|
||||
const bool show_unit_colour = preferences::show_side_colours() && it != units_.end();
|
||||
const bool show_unit_colour = preferences::show_side_colours() && !fogged(x,y) && it != units_.end();
|
||||
if(show_unit_colour) {
|
||||
const SDL_Color& colour = font::get_side_colour(it->second.side());
|
||||
grid_colour = SDL_MapRGB(dst->format,colour.r,colour.g,colour.b);
|
||||
|
@ -1344,13 +1344,14 @@ void display::draw_footstep(const gamemap::location& loc, int xloc, int yloc)
|
|||
draw_unit(xloc,yloc,image,hflip,vflip,0.5);
|
||||
|
||||
if(show_time && route_.move_left > 0 && route_.move_left < 10) {
|
||||
const SDL_Rect rect = {0,0,this->mapx(),this->y()};
|
||||
static std::string str(1,'x');
|
||||
str[0] = '0' + route_.move_left + 1;
|
||||
const SDL_Rect& text_area =
|
||||
font::draw_text(NULL,screen_area(),18,font::BUTTON_COLOUR,str,0,0);
|
||||
font::draw_text(NULL,rect,18,font::BUTTON_COLOUR,str,0,0);
|
||||
const int x = xloc + int(zoom_/2.0) - text_area.w/2;
|
||||
const int y = yloc + int(zoom_/2.0) - text_area.h/2;
|
||||
font::draw_text(this,screen_area(),18,font::BUTTON_COLOUR,str,x,y);
|
||||
font::draw_text(this,rect,18,font::BUTTON_COLOUR,str,x,y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
try {
|
||||
LEVEL_RESULT res = REPLAY;
|
||||
|
||||
state.label = scenario->values["name"];
|
||||
state.label = translate_string_default((*scenario)["id"],(*scenario)["name"]);
|
||||
|
||||
recorder.set_save_info(state);
|
||||
|
||||
|
@ -122,7 +122,7 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
|
||||
//if this isn't the last scenario, then save the game
|
||||
if(scenario != NULL) {
|
||||
state.label = (*scenario)["name"];
|
||||
state.label = translate_string_default((*scenario)["id"],(*scenario)["name"]);
|
||||
|
||||
const int should_save = dialogs::get_save_name(disp,
|
||||
string_table["save_game_message"],
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace game_config
|
|||
const int cure_amount = 8;
|
||||
const int curer_heals_per_turn = 18;
|
||||
const int recall_cost = 20;
|
||||
const std::string version = "0.6RC2";
|
||||
const std::string version = "0.6RC3";
|
||||
bool debug = false;
|
||||
|
||||
#ifdef WESNOTH_PATH
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <cstdlib>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
@ -134,6 +135,7 @@ std::map<gamemap::location,unit>* units = NULL;
|
|||
std::vector<team>* teams = NULL;
|
||||
game_state* state_of_game = NULL;
|
||||
game_data* game_data_ptr = NULL;
|
||||
std::set<std::string> used_items;
|
||||
|
||||
bool events_init() { return screen != NULL; }
|
||||
|
||||
|
@ -173,7 +175,7 @@ public:
|
|||
return cfg_->children["filter_second"];
|
||||
}
|
||||
|
||||
void handle_event(const queued_event& event_info, config* cfg=NULL);
|
||||
void handle_event(const queued_event& event_info, const config* cfg=NULL);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
@ -218,31 +220,79 @@ std::vector<gamemap::location> multiple_locs(const config& cfg)
|
|||
|
||||
std::multimap<std::string,event_handler> events_map;
|
||||
|
||||
void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
||||
void event_handler::handle_event(const queued_event& event_info, const config* cfg)
|
||||
{
|
||||
if(cfg == NULL)
|
||||
cfg = cfg_;
|
||||
|
||||
std::vector<config*>::const_iterator i;
|
||||
|
||||
//sub commands that need to be handled in a guaranteed ordering
|
||||
std::vector<config*>& commands = cfg->children["command"];
|
||||
for(std::vector<config*>::iterator cmd = commands.begin();
|
||||
cmd != commands.end(); ++cmd) {
|
||||
handle_event(event_info,*cmd);
|
||||
const config::child_list& commands = cfg->get_children("command");
|
||||
for(i = commands.begin(); i != commands.end(); ++i) {
|
||||
handle_event(event_info,*i);
|
||||
}
|
||||
|
||||
//allow a side to recruit a new type of unit
|
||||
const config::child_list& allow_recruit = cfg->get_children("allow_recruit");
|
||||
for(i = allow_recruit.begin(); i != allow_recruit.end(); ++i) {
|
||||
const int side = maximum<int>(1,atoi((**i)["side"].c_str()));
|
||||
const size_t index = side-1;
|
||||
if(index > teams->size())
|
||||
continue;
|
||||
|
||||
const std::string& type = (**i)["type"];
|
||||
(*teams)[index].recruits().insert(type);
|
||||
if(index == 0) {
|
||||
state_of_game->can_recruit.insert(type);
|
||||
}
|
||||
}
|
||||
|
||||
//remove the ability to recruit a unit from a certain side
|
||||
const config::child_list& disallow_recruit = cfg->get_children("disallow_recruit");
|
||||
for(i = disallow_recruit.begin(); i != disallow_recruit.end(); ++i) {
|
||||
const int side = maximum<int>(1,atoi((**i)["side"].c_str()));
|
||||
const size_t index = side-1;
|
||||
if(index > teams->size())
|
||||
continue;
|
||||
|
||||
const std::string& type = (**i)["type"];
|
||||
(*teams)[index].recruits().erase(type);
|
||||
if(index == 0) {
|
||||
state_of_game->can_recruit.erase(type);
|
||||
}
|
||||
}
|
||||
|
||||
const config::child_list& set_recruit = cfg->get_children("set_recruit");
|
||||
for(i = set_recruit.begin(); i != set_recruit.end(); ++i) {
|
||||
const int side = maximum<int>(1,atoi((**i)["side"].c_str()));
|
||||
const size_t index = side-1;
|
||||
if(index > teams->size())
|
||||
continue;
|
||||
|
||||
std::vector<std::string> recruit = config::split((**i)["recruit"]);
|
||||
if(recruit.size() == 1 && recruit.back() == "")
|
||||
recruit.clear();
|
||||
|
||||
std::set<std::string>& can_recruit = (*teams)[index].recruits();
|
||||
can_recruit.clear();
|
||||
std::copy(recruit.begin(),recruit.end(),std::inserter(can_recruit,can_recruit.end()));
|
||||
if(index == 0) {
|
||||
state_of_game->can_recruit = can_recruit;
|
||||
}
|
||||
}
|
||||
|
||||
//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"]);
|
||||
const config::child_list& sounds = cfg->get_children("sound");
|
||||
for(i = sounds.begin(); i != sounds.end(); ++i) {
|
||||
sound::play_sound((**i)["name"]);
|
||||
}
|
||||
|
||||
std::vector<config*>& colour_adjust = cfg->children["colour_adjust"];
|
||||
for(std::vector<config*>::const_iterator col = colour_adjust.begin();
|
||||
col != colour_adjust.end(); ++col) {
|
||||
const int r = atoi((**col)["red"].c_str());
|
||||
const int g = atoi((**col)["green"].c_str());
|
||||
const int b = atoi((**col)["blue"].c_str());
|
||||
const config::child_list& colour_adjust = cfg->get_children("colour_adjust");
|
||||
for(i = colour_adjust.begin(); i != colour_adjust.end(); ++i) {
|
||||
const int r = atoi((**i)["red"].c_str());
|
||||
const int g = atoi((**i)["green"].c_str());
|
||||
const int b = atoi((**i)["blue"].c_str());
|
||||
screen->adjust_colours(r,g,b);
|
||||
screen->invalidate_all();
|
||||
screen->draw(true,true);
|
||||
|
@ -276,11 +326,10 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//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 config::child_list& gold = cfg->get_children("gold");
|
||||
for(i = gold.begin(); i != gold.end(); ++i) {
|
||||
const std::string& side = (**i)["side"];
|
||||
const std::string& amount = (**i)["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;
|
||||
|
@ -291,16 +340,14 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
|
||||
//moving a 'unit' - i.e. a dummy unit that is just moving for
|
||||
//the visual effect
|
||||
std::vector<config*>& move_unit_fake = cfg->children["move_unit_fake"];
|
||||
for(std::vector<config*>::iterator muf = move_unit_fake.begin();
|
||||
muf != move_unit_fake.end(); ++muf) {
|
||||
const std::string& type = (*muf)->values["type"];
|
||||
const game_data::unit_type_map::const_iterator itor =
|
||||
game_data_ptr->unit_types.find(type);
|
||||
const config::child_list& move_unit_fake = cfg->get_children("move_unit_fake");
|
||||
for(i = move_unit_fake.begin(); i != move_unit_fake.end(); ++i) {
|
||||
const std::string& type = (**i)["type"];
|
||||
const game_data::unit_type_map::const_iterator itor = game_data_ptr->unit_types.find(type);
|
||||
if(itor != game_data_ptr->unit_types.end()) {
|
||||
unit dummy_unit(&itor->second,0);
|
||||
const std::vector<std::string> xvals = config::split((*muf)->values["x"]);
|
||||
const std::vector<std::string> yvals = config::split((*muf)->values["y"]);
|
||||
const std::vector<std::string> xvals = config::split((**i)["x"]);
|
||||
const std::vector<std::string> yvals = config::split((**i)["y"]);
|
||||
std::vector<gamemap::location> path;
|
||||
for(size_t i = 0; i != minimum(xvals.size(),yvals.size()); ++i) {
|
||||
path.push_back(gamemap::location(atoi(xvals[i].c_str())-1,
|
||||
|
@ -312,17 +359,16 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//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) {
|
||||
string_map& vals = (*var)->values;
|
||||
const std::string& name = vals["name"];
|
||||
const std::string& value = vals["value"];
|
||||
const config::child_list& set_vars = cfg->get_children("set_variable");
|
||||
for(i = set_vars.begin(); i != set_vars.end(); ++i) {
|
||||
|
||||
const std::string& name = (**i)["name"];
|
||||
const std::string& value = (**i)["value"];
|
||||
if(value.empty() == false) {
|
||||
state_of_game->variables[name] = value;
|
||||
}
|
||||
|
||||
const std::string& add = vals["add"];
|
||||
const std::string& add = (**i)["add"];
|
||||
if(add.empty() == false) {
|
||||
double value = atof(state_of_game->variables[name].c_str());
|
||||
value += atof(add.c_str());
|
||||
|
@ -331,7 +377,7 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
state_of_game->variables[name] = buf;
|
||||
}
|
||||
|
||||
const std::string& multiply = vals["multiply"];
|
||||
const std::string& multiply = (**i)["multiply"];
|
||||
if(multiply.empty() == false) {
|
||||
double value = atof(state_of_game->variables[name].c_str());
|
||||
value *= atof(multiply.c_str());
|
||||
|
@ -342,28 +388,26 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//conditional statements
|
||||
std::vector<config*>& conditionals = cfg->children["if"];
|
||||
for(std::vector<config*>::iterator cond = conditionals.begin();
|
||||
cond != conditionals.end(); ++cond) {
|
||||
const config::child_list& conditionals = cfg->get_children("if");
|
||||
for(i = conditionals.begin(); i != conditionals.end(); ++i) {
|
||||
const std::string type = game_events::conditional_passed(
|
||||
*state_of_game,units,**cond) ? "then":"else";
|
||||
*state_of_game,units,**i) ? "then":"else";
|
||||
|
||||
//if the if statement passed, then execute all 'then' statements,
|
||||
//otherwise execute 'else' statements
|
||||
std::vector<config*>& commands = (*cond)->children[type];
|
||||
for(std::vector<config*>::iterator cmd = commands.begin();
|
||||
const std::vector<config*>& commands = (*i)->get_children(type);
|
||||
for(std::vector<config*>::const_iterator cmd = commands.begin();
|
||||
cmd != commands.end(); ++cmd) {
|
||||
handle_event(event_info,*cmd);
|
||||
}
|
||||
}
|
||||
|
||||
//if we are assigning a role to a unit from the available units list
|
||||
std::vector<config*>& assign_role = cfg->children["role"];
|
||||
for(std::vector<config*>::iterator rl = assign_role.begin();
|
||||
rl != assign_role.end(); ++rl) {
|
||||
const config::child_list& assign_role = cfg->get_children("role");
|
||||
for(i = assign_role.begin(); i != assign_role.end(); ++i) {
|
||||
|
||||
//get a list of the types this unit can be
|
||||
std::vector<std::string> types = config::split((*rl)->values["type"]);
|
||||
std::vector<std::string> types = config::split((**i)["type"]);
|
||||
|
||||
//iterate over all the types, and for each type, try to find
|
||||
//a unit that matches
|
||||
|
@ -375,7 +419,7 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
std::map<gamemap::location,unit>::iterator itor;
|
||||
for(itor = units->begin(); itor != units->end(); ++itor) {
|
||||
if(itor->second.matches_filter(cfg)) {
|
||||
itor->second.assign_role((*rl)->values["role"]);
|
||||
itor->second.assign_role((**i)["role"]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +432,7 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
for(ui = state_of_game->available_units.begin();
|
||||
ui != state_of_game->available_units.end(); ++ui) {
|
||||
if(ui->matches_filter(cfg)) {
|
||||
ui->assign_role((*rl)->values["role"]);
|
||||
ui->assign_role((**i)["role"]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -404,10 +448,9 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
break;
|
||||
}
|
||||
|
||||
std::vector<config*>& remove_overlays = cfg->children["removeitem"];
|
||||
for(std::vector<config*>::iterator rm = remove_overlays.begin();
|
||||
rm != remove_overlays.end(); ++rm) {
|
||||
gamemap::location loc(**rm);
|
||||
const config::child_list& remove_overlays = cfg->get_children("removeitem");
|
||||
for(i = remove_overlays.begin(); i != remove_overlays.end(); ++i) {
|
||||
gamemap::location loc(**i);
|
||||
if(!loc.valid()) {
|
||||
loc = event_info.loc1;
|
||||
}
|
||||
|
@ -416,25 +459,23 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//hiding units
|
||||
std::vector<config*>& hide = cfg->children["hide_unit"];
|
||||
for(std::vector<config*>::iterator hd = hide.begin();
|
||||
hd != hide.end(); ++hd) {
|
||||
const gamemap::location loc(**hd);
|
||||
const config::child_list& hide = cfg->get_children("hide_unit");
|
||||
for(i = hide.begin(); i != hide.end(); ++i) {
|
||||
const gamemap::location loc(**i);
|
||||
screen->hide_unit(loc);
|
||||
screen->draw_tile(loc.x,loc.y);
|
||||
}
|
||||
|
||||
if(cfg->children["unhide_unit"].empty() == false) {
|
||||
if(cfg->child("unhide_unit") != NULL) {
|
||||
const gamemap::location loc = screen->hide_unit(gamemap::location());
|
||||
screen->draw_tile(loc.x,loc.y);
|
||||
}
|
||||
|
||||
//adding new items
|
||||
std::vector<config*>& add_overlays = cfg->children["item"];
|
||||
for(std::vector<config*>::iterator ni = add_overlays.begin();
|
||||
ni != add_overlays.end(); ++ni) {
|
||||
gamemap::location loc(**ni);
|
||||
const std::string& img = (*ni)->values["image"];
|
||||
const config::child_list& add_overlays = cfg->get_children("item");
|
||||
for(i = add_overlays.begin(); i != add_overlays.end(); ++i) {
|
||||
gamemap::location loc(**i);
|
||||
const std::string& img = (**i)["image"];
|
||||
if(!img.empty()) {
|
||||
screen->add_overlay(loc,img);
|
||||
screen->draw_tile(loc.x,loc.y);
|
||||
|
@ -442,13 +483,12 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//changing the terrain
|
||||
std::vector<config*>& terrain_changes = cfg->children["terrain"];
|
||||
for(std::vector<config*>::iterator tc = terrain_changes.begin();
|
||||
tc != terrain_changes.end(); ++tc) {
|
||||
const std::vector<gamemap::location> locs = multiple_locs(**tc);
|
||||
const config::child_list& terrain_changes = cfg->get_children("terrain");
|
||||
for(i = terrain_changes.begin(); i != terrain_changes.end(); ++i) {
|
||||
const std::vector<gamemap::location> locs = multiple_locs(**i);
|
||||
|
||||
for(std::vector<gamemap::location>::const_iterator loc = locs.begin(); loc != locs.end(); ++loc) {
|
||||
const std::string& terrain_type = (**tc)["letter"];
|
||||
const std::string& terrain_type = (**i)["letter"];
|
||||
if(terrain_type.size() > 0) {
|
||||
game_map->set_terrain(*loc,terrain_type[0]);
|
||||
screen->recalculate_minimap();
|
||||
|
@ -458,11 +498,10 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//if we should spawn a new unit on the map somewhere
|
||||
std::vector<config*>& new_units = cfg->children["unit"];
|
||||
for(std::vector<config*>::iterator ui = new_units.begin();
|
||||
ui != new_units.end(); ++ui) {
|
||||
unit new_unit(*game_data_ptr,**ui);
|
||||
gamemap::location loc(**ui);
|
||||
const config::child_list& new_units = cfg->get_children("unit");
|
||||
for(i = new_units.begin(); i != new_units.end(); ++i) {
|
||||
unit new_unit(*game_data_ptr,**i);
|
||||
gamemap::location loc(**i);
|
||||
|
||||
if(game_map->on_board(loc)) {
|
||||
loc = find_vacant_tile(*game_map,*units,loc);
|
||||
|
@ -474,32 +513,28 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
}
|
||||
|
||||
//if we should recall units that match a certain description
|
||||
std::vector<config*>& recalls = cfg->children["recall"];
|
||||
for(std::vector<config*>::iterator ir = recalls.begin();
|
||||
ir != recalls.end(); ++ir) {
|
||||
const config::child_list& recalls = cfg->get_children("recall");
|
||||
for(i = recalls.begin(); i != recalls.end(); ++i) {
|
||||
std::vector<unit>& avail = state_of_game->available_units;
|
||||
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,false);
|
||||
for(std::vector<unit>::iterator u = avail.begin(); u != avail.end(); ++u) {
|
||||
if(u->matches_filter(**i)) {
|
||||
recruit_unit(*game_map,1,*units,*u,gamemap::location(),screen,false);
|
||||
avail.erase(u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<config*>& objects = cfg->children["object"];
|
||||
for(std::vector<config*>::iterator obj = objects.begin();
|
||||
obj != objects.end(); ++obj) {
|
||||
string_map& values = (*obj)->values;
|
||||
|
||||
//if this item has already been used
|
||||
if(values["used"].empty() == false)
|
||||
continue;
|
||||
const config::child_list& objects = cfg->get_children("object");
|
||||
for(i = objects.begin(); i != objects.end(); ++i) {
|
||||
const config& values = **i;
|
||||
|
||||
const std::string& id = values["id"];
|
||||
|
||||
//if this item has already been used
|
||||
if(used_items.count(id))
|
||||
continue;
|
||||
|
||||
const std::string image = values["image"];
|
||||
std::string caption = values["name"];
|
||||
|
||||
|
@ -507,15 +542,14 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
if(caption_lang.empty() == false)
|
||||
caption = caption_lang;
|
||||
|
||||
const std::map<gamemap::location,unit>::iterator u =
|
||||
units->find(event_info.loc1);
|
||||
const std::map<gamemap::location,unit>::iterator u = units->find(event_info.loc1);
|
||||
|
||||
if(u == units->end())
|
||||
continue;
|
||||
|
||||
std::string text;
|
||||
|
||||
std::vector<config*>& filters = (*obj)->children["filter"];
|
||||
const config::child_list& filters = (*i)->get_children("filter");
|
||||
|
||||
if(filters.empty() || u->second.matches_filter(*filters[0])) {
|
||||
const std::string& lang = string_table[id];
|
||||
|
@ -524,13 +558,13 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
else
|
||||
text = values["description"];
|
||||
|
||||
u->second.add_modification("object",**obj);
|
||||
u->second.add_modification("object",**i);
|
||||
screen->remove_overlay(event_info.loc1);
|
||||
screen->select_hex(event_info.loc1);
|
||||
screen->invalidate_unit();
|
||||
|
||||
//mark that this item won't be used again
|
||||
values["used"] = "true";
|
||||
used_items.insert(id);
|
||||
} else {
|
||||
const std::string& lang = string_table[id + "_cannot_use"];
|
||||
if(!lang.empty())
|
||||
|
@ -551,10 +585,9 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
screen->draw();
|
||||
}
|
||||
|
||||
std::vector<config*>& messages = cfg->children["message"];
|
||||
for(std::vector<config*>::iterator msg = messages.begin();
|
||||
msg != messages.end(); ++msg) {
|
||||
string_map& values = (*msg)->values;
|
||||
const config::child_list& messages = cfg->get_children("message");
|
||||
for(i = messages.begin(); i != messages.end(); ++i) {
|
||||
const config& values = **i;
|
||||
|
||||
std::map<gamemap::location,unit>::iterator speaker = units->end();
|
||||
if(values["speaker"] == "unit") {
|
||||
|
@ -564,7 +597,7 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
} else if(values["speaker"] != "narrator") {
|
||||
for(speaker = units->begin(); speaker != units->end();
|
||||
++speaker){
|
||||
if(speaker->second.matches_filter(**msg))
|
||||
if(speaker->second.matches_filter(**i))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -575,21 +608,21 @@ 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& sfx = values["sound"];
|
||||
if(sfx != "") {
|
||||
sound::play_sound(sfx);
|
||||
}
|
||||
|
||||
const std::string& id = values["id"];
|
||||
|
||||
std::string image = (*msg)->values["image"];
|
||||
std::string image = values["image"];
|
||||
std::string caption;
|
||||
|
||||
const std::string& lang_caption = string_table[id + "_caption"];
|
||||
if(!lang_caption.empty())
|
||||
caption = lang_caption;
|
||||
else
|
||||
caption = (*msg)->values["caption"];
|
||||
caption = values["caption"];
|
||||
|
||||
if(speaker != units->end()) {
|
||||
screen->highlight_hex(speaker->first);
|
||||
|
@ -610,12 +643,12 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
std::vector<std::string> options;
|
||||
std::vector<std::vector<config*>*> option_events;
|
||||
|
||||
std::vector<config*>& menu_items = (*msg)->children["option"];
|
||||
for(std::vector<config*>::iterator mi = menu_items.begin();
|
||||
std::cerr << "building menu items...\n";
|
||||
|
||||
const std::vector<config*>& menu_items = (*i)->get_children("option");
|
||||
for(std::vector<config*>::const_iterator mi = menu_items.begin();
|
||||
mi != menu_items.end(); ++mi) {
|
||||
const std::string& lang_msg = string_table[(*mi)->values["id"]];
|
||||
const std::string& msg = lang_msg.empty() ?
|
||||
(*mi)->values["message"] : lang_msg;
|
||||
const std::string& msg = translate_string_default((**mi)["id"],(**mi)["message"]);
|
||||
options.push_back(msg);
|
||||
option_events.push_back(&(*mi)->children["command"]);
|
||||
}
|
||||
|
@ -638,8 +671,11 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
throw replay::error();
|
||||
}
|
||||
|
||||
const std::string& val =
|
||||
cfg->children["choose"].front()->values["value"];
|
||||
if(size_t(option_chosen) >= options.size()) {
|
||||
option_chosen = 0;
|
||||
}
|
||||
|
||||
const std::string& val = cfg->children["choose"].front()->values["value"];
|
||||
option_chosen = atol(val.c_str());
|
||||
|
||||
} else if(options.empty() == false) {
|
||||
|
@ -648,40 +684,38 @@ void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|||
|
||||
if(options.empty() == false) {
|
||||
assert(size_t(option_chosen) < menu_items.size());
|
||||
std::vector<config*>& events = *option_events[option_chosen];
|
||||
for(std::vector<config*>::iterator ev = events.begin();
|
||||
const std::vector<config*>& events = *option_events[option_chosen];
|
||||
for(std::vector<config*>::const_iterator ev = events.begin();
|
||||
ev != events.end(); ++ev) {
|
||||
handle_event(event_info,*ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<config*>& dead_units = cfg->children["kill"];
|
||||
for(std::vector<config*>::iterator du = dead_units.begin();
|
||||
du != dead_units.end(); ++du) {
|
||||
const config::child_list& dead_units = cfg->get_children("kill");
|
||||
for(i = dead_units.begin(); i != dead_units.end(); ++i) {
|
||||
|
||||
for(std::map<gamemap::location,unit>::iterator i = units->begin();
|
||||
i != units->end(); ++i) {
|
||||
while(i->second.matches_filter(**du) && i != units->end()) {
|
||||
units->erase(i);
|
||||
i = units->begin();
|
||||
for(std::map<gamemap::location,unit>::iterator un = units->begin();
|
||||
un != units->end(); ++un) {
|
||||
while(un != units->end() && un->second.matches_filter(**i)) {
|
||||
units->erase(un);
|
||||
un = units->begin();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unit>& avail_units = state_of_game->available_units;
|
||||
for(std::vector<unit>::iterator j = avail_units.begin();
|
||||
j != avail_units.end(); ++j) {
|
||||
while(j->matches_filter(**du) && j != avail_units.end()) {
|
||||
while(j != avail_units.end() && j->matches_filter(**i)) {
|
||||
j = avail_units.erase(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//adding of new events
|
||||
std::vector<config*>& new_events = cfg->children["event"];
|
||||
for(std::vector<config*>::iterator ne = new_events.begin();
|
||||
ne != new_events.end(); ++ne) {
|
||||
event_handler new_handler(*ne);
|
||||
const config::child_list& new_events = cfg->get_children("event");
|
||||
for(i = new_events.begin(); i != new_events.end(); ++i) {
|
||||
event_handler new_handler(*i);
|
||||
events_map.insert(std::pair<std::string,event_handler>(
|
||||
new_handler.name(),new_handler));
|
||||
}
|
||||
|
@ -832,6 +866,8 @@ manager::manager(config& cfg, display& gui_, gamemap& map_,
|
|||
units = &units_;
|
||||
state_of_game = &state_of_game_;
|
||||
game_data_ptr = &game_data_;
|
||||
|
||||
used_items.clear();
|
||||
}
|
||||
|
||||
manager::~manager() {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
time_of_day::time_of_day(config& cfg)
|
||||
|
@ -117,6 +118,14 @@ game_state read_game(game_data& data, config* cfg)
|
|||
res.starting_pos = *starts[0];
|
||||
}
|
||||
|
||||
res.can_recruit.clear();
|
||||
|
||||
const std::string& can_recruit_str = (*cfg)["can_recruit"];
|
||||
if(can_recruit_str != "") {
|
||||
const std::vector<std::string> can_recruit = config::split(can_recruit_str);
|
||||
std::copy(can_recruit.begin(),can_recruit.end(),std::inserter(res.can_recruit,res.can_recruit.end()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -151,6 +160,16 @@ void write_game(const game_state& game, config& cfg)
|
|||
}
|
||||
|
||||
cfg.children["start"].push_back(new config(game.starting_pos));
|
||||
|
||||
std::stringstream can_recruit;
|
||||
std::copy(game.can_recruit.begin(),game.can_recruit.end(),std::ostream_iterator<std::string>(can_recruit,","));
|
||||
std::string can_recruit_str = can_recruit.str();
|
||||
|
||||
//remove the trailing comma
|
||||
if(can_recruit_str.size() > 0)
|
||||
can_recruit_str.resize(can_recruit_str.size()-1);
|
||||
|
||||
cfg["can_recruit"] = can_recruit_str;
|
||||
}
|
||||
|
||||
//a structure for comparing to save_info objects based on their modified time.
|
||||
|
|
|
@ -88,10 +88,12 @@ struct game_state
|
|||
std::string campaign_type; //type of the game - campaign, multiplayer etc
|
||||
std::string scenario; //the scenario being played
|
||||
int gold; //amount of gold the player has saved
|
||||
std::vector<unit> available_units; //units the player has to recall
|
||||
std::vector<unit> available_units; //units the player may recall
|
||||
std::map<std::string,std::string> variables; //variables that have been set
|
||||
std::string difficulty; //the difficulty level the game is being played on.
|
||||
|
||||
std::set<std::string> can_recruit; //units the player has the ability to recruit
|
||||
|
||||
//if the game is saved mid-level, we have a series of replay steps to
|
||||
//take the game up to the position it was saved at.
|
||||
config replay_data;
|
||||
|
|
|
@ -36,7 +36,7 @@ const std::string& translate_string(const std::string& str)
|
|||
const std::string& translate_string_default(const std::string& str, const std::string& default_val)
|
||||
{
|
||||
const string_map::const_iterator i = string_table.find(str);
|
||||
if(i != string_table.end())
|
||||
if(i != string_table.end() && i->second != "")
|
||||
return i->second;
|
||||
else
|
||||
return default_val;
|
||||
|
|
|
@ -64,10 +64,10 @@ gamemap::TERRAIN gamemap::underlying_terrain(TERRAIN terrain) const
|
|||
}
|
||||
}
|
||||
|
||||
gamemap::location::location(config& cfg) : x(-1), y(-1)
|
||||
gamemap::location::location(const config& cfg) : x(-1), y(-1)
|
||||
{
|
||||
const std::string& xstr = cfg.values["x"];
|
||||
const std::string& ystr = cfg.values["y"];
|
||||
const std::string& xstr = cfg["x"];
|
||||
const std::string& ystr = cfg["y"];
|
||||
|
||||
//the co-ordinates in config files will be 1-based, while we
|
||||
//want them as 0-based
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
location() : x(-1), y(-1) {}
|
||||
location(int x, int y) : x(x), y(y) {}
|
||||
location(config& cfg);
|
||||
location(const config& cfg);
|
||||
|
||||
bool valid() const { return x >= 0 && y >= 0; }
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "tooltips.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
||||
config* level, CVideo& video,
|
||||
|
@ -68,26 +69,35 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
if(gold.empty())
|
||||
gold = "100";
|
||||
|
||||
const int minimum_gold = 100;
|
||||
|
||||
int ngold = ::atoi(gold.c_str());
|
||||
if(ui == unit_cfg.begin() && state_of_game.gold >= minimum_gold &&
|
||||
if(ui == unit_cfg.begin() && state_of_game.gold >= ngold &&
|
||||
(*level)["disallow_recall"] != "yes")
|
||||
ngold = state_of_game.gold;
|
||||
|
||||
const gamemap::location& start_pos =
|
||||
map.starting_position(new_unit.side());
|
||||
const gamemap::location& start_pos = map.starting_position(new_unit.side());
|
||||
|
||||
if(!start_pos.valid()) {
|
||||
std::stringstream err;
|
||||
err << "No starting position for side " << new_unit.side();
|
||||
throw gamestatus::load_game_failed(err.str());
|
||||
if(!start_pos.valid() && new_unit.side() == 1) {
|
||||
throw gamestatus::load_game_failed("No starting position for side 1");
|
||||
}
|
||||
|
||||
if(start_pos.valid()) {
|
||||
units.insert(std::pair<gamemap::location,unit>(
|
||||
map.starting_position(new_unit.side()), new_unit));
|
||||
}
|
||||
|
||||
units.insert(std::pair<gamemap::location,unit>(
|
||||
map.starting_position(new_unit.side()), new_unit));
|
||||
teams.push_back(team(**ui,ngold));
|
||||
|
||||
//if the game state specifies units that can be recruited for the player
|
||||
//then add them
|
||||
if(teams.size() == 1 && state_of_game.can_recruit.empty() == false) {
|
||||
std::copy(state_of_game.can_recruit.begin(),state_of_game.can_recruit.end(),
|
||||
std::inserter(teams.back().recruits(),teams.back().recruits().end()));
|
||||
}
|
||||
|
||||
if(teams.size() == 1) {
|
||||
state_of_game.can_recruit = teams.back().recruits();
|
||||
}
|
||||
|
||||
if(first_human_team == -1 && teams.back().is_human()) {
|
||||
first_human_team = teams.size()-1;
|
||||
}
|
||||
|
@ -373,10 +383,6 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
} catch(end_level_exception&) {
|
||||
}
|
||||
|
||||
if((*level)["disallow_recall"] == "yes") {
|
||||
return VICTORY;
|
||||
}
|
||||
|
||||
//add all the units that survived the scenario
|
||||
for(std::map<gamemap::location,unit>::iterator un =
|
||||
units.begin(); un != units.end(); ++un) {
|
||||
|
@ -387,6 +393,10 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
|
|||
}
|
||||
}
|
||||
|
||||
if((*level)["disallow_recall"] == "yes") {
|
||||
return VICTORY;
|
||||
}
|
||||
|
||||
const int remaining_gold = teams[0].gold();
|
||||
const int finishing_bonus_per_turn =
|
||||
map.towers().size()*game_config::tower_income;
|
||||
|
|
|
@ -613,6 +613,11 @@ void turn_info::show_menu()
|
|||
menu.push_back(string_table[*items]);
|
||||
}
|
||||
|
||||
static const std::string create_unit_debug = "Create Unit (debug)";
|
||||
if(game_config::debug) {
|
||||
menu.push_back(create_unit_debug);
|
||||
}
|
||||
|
||||
if(un != units_.end()) {
|
||||
menu.push_back(string_table["describe_unit"]);
|
||||
|
||||
|
@ -631,7 +636,24 @@ void turn_info::show_menu()
|
|||
menu.pop_back();
|
||||
}
|
||||
|
||||
if(result == string_table["describe_unit"]) {
|
||||
if(result == create_unit_debug) {
|
||||
std::vector<std::string> options;
|
||||
std::vector<unit> unit_choices;
|
||||
for(game_data::unit_type_map::const_iterator i = gameinfo_.unit_types.begin();
|
||||
i != gameinfo_.unit_types.end(); ++i) {
|
||||
options.push_back(i->first);
|
||||
unit_choices.push_back(unit(&i->second,1,false));
|
||||
}
|
||||
|
||||
const int choice = gui::show_dialog(gui_,NULL,"","Create unit (debug):",
|
||||
gui::OK_CANCEL,&options,&unit_choices);
|
||||
if(choice >= 0 && choice < unit_choices.size()) {
|
||||
units_.erase(last_hex_);
|
||||
units_.insert(std::pair<gamemap::location,unit>(last_hex_,unit_choices[choice]));
|
||||
gui_.invalidate(last_hex_);
|
||||
gui_.invalidate_unit();
|
||||
}
|
||||
} else if(result == string_table["describe_unit"]) {
|
||||
unit_description();
|
||||
} else if(result == string_table["rename_unit"]) {
|
||||
rename_unit();
|
||||
|
@ -1003,7 +1025,7 @@ void turn_info::rename_unit()
|
|||
void turn_info::save_game()
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << translate_string(state_of_game_.scenario) << " " << string_table["turn"]
|
||||
stream << state_of_game_.label << " " << string_table["turn"]
|
||||
<< " " << status_.turn();
|
||||
std::string label = stream.str();
|
||||
|
||||
|
@ -1189,8 +1211,12 @@ void turn_info::recall()
|
|||
<< string_table["level"] << ": "
|
||||
<< unit->type().level() << ","
|
||||
<< string_table["xp"] << ": "
|
||||
<< unit->experience() << "/"
|
||||
<< unit->max_experience();
|
||||
<< unit->experience() << "/";
|
||||
|
||||
if(unit->type().advances_to().empty())
|
||||
option << "-";
|
||||
else
|
||||
option << unit->max_experience();
|
||||
options.push_back(option.str());
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,16 @@ int get_random()
|
|||
return random_generator->get_random();
|
||||
}
|
||||
|
||||
const config* get_random_results()
|
||||
{
|
||||
return random_generator->get_random_results();
|
||||
}
|
||||
|
||||
void set_random_results(const config& cfg)
|
||||
{
|
||||
random_generator->set_random_results(cfg);
|
||||
}
|
||||
|
||||
replay::replay() : pos_(0), current_(NULL), skip_(0)
|
||||
{}
|
||||
|
||||
|
@ -287,6 +297,19 @@ int replay::get_random()
|
|||
}
|
||||
}
|
||||
|
||||
const config* replay::get_random_results() const
|
||||
{
|
||||
assert(current_ != NULL);
|
||||
return current_->child("results");
|
||||
}
|
||||
|
||||
void replay::set_random_results(const config& cfg)
|
||||
{
|
||||
assert(current_ != NULL);
|
||||
current_->children["results"].clear();
|
||||
current_->children["results"].push_back(new config(cfg));
|
||||
}
|
||||
|
||||
void replay::start_replay()
|
||||
{
|
||||
pos_ = 0;
|
||||
|
@ -537,7 +560,9 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
std::map<gamemap::location,unit>::const_iterator tgt = units.find(dst);
|
||||
|
||||
if(tgt == units.end()) {
|
||||
std::cerr << "unfound defender for attack\n";
|
||||
std::cerr << "unfound defender for attack: "
|
||||
<< (src.x+1) << "," << (src.y+1) << " -> "
|
||||
<< (dst.x+1) << "," << (dst.y+1) << "\n";
|
||||
throw replay::error();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
int get_random();
|
||||
|
||||
const config* get_random_results();
|
||||
void set_random_results(const config& cfg);
|
||||
|
||||
class replay
|
||||
{
|
||||
public:
|
||||
|
@ -50,6 +53,8 @@ public:
|
|||
void undo();
|
||||
|
||||
int get_random();
|
||||
const config* get_random_results() const;
|
||||
void set_random_results(const config& cfg);
|
||||
|
||||
void start_replay();
|
||||
config* get_next_action();
|
||||
|
|
|
@ -379,7 +379,7 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
text_widget_height + check_button_height;
|
||||
|
||||
if(total_width > scr->w - 100 || total_height > scr->h - 100)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
int xloc = scr->w/2 - total_width/2;
|
||||
int yloc = scr->h/2 - total_height/2;
|
||||
|
@ -399,9 +399,12 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
|
||||
//make sure that the dialog doesn't overlap the right part of the screen
|
||||
if(xloc + total_width+border_size >= disp.mapx()-1) {
|
||||
std::cerr << "in if...\n";
|
||||
xloc = disp.mapx()-(total_width+border_size+2);
|
||||
if(xloc < 0)
|
||||
return -1;
|
||||
if(xloc < 0) {
|
||||
std::cerr << "dialog is too large to fit on-screen!\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const int button_hpadding = total_width - button_widths;
|
||||
|
|
|
@ -157,6 +157,11 @@ const std::set<std::string>& team::recruits() const
|
|||
return info_.can_recruit;
|
||||
}
|
||||
|
||||
std::set<std::string>& team::recruits()
|
||||
{
|
||||
return info_.can_recruit;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& team::recruitment_pattern() const
|
||||
{
|
||||
return info_.recruitment_pattern;
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
void spend_gold(int amount);
|
||||
|
||||
const std::set<std::string>& recruits() const;
|
||||
std::set<std::string>& recruits();
|
||||
const std::vector<std::string>& recruitment_pattern() const;
|
||||
const std::string& name() const;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue