merged syncpoint_gettext1_1 from trunk
This commit is contained in:
parent
dc3202ddc5
commit
4c9a6d303f
81 changed files with 1551 additions and 461 deletions
18
changelog
18
changelog
|
@ -1,3 +1,21 @@
|
|||
CVS HEAD:
|
||||
* multiplayer improvements:
|
||||
* new map: Battle for Weslin Bridge
|
||||
* new map: Forest of Fear
|
||||
* clipboard support for X11
|
||||
* new rightside panel
|
||||
* improved lite buttons
|
||||
* improved clipboard functions
|
||||
* various help browser improvements
|
||||
* made The Eastern Invasion campaign translatable
|
||||
* added icons for preferences and multiplayer dialogs
|
||||
* fixed crash when loading an empty map
|
||||
* fixed transition problems with forests
|
||||
* fixed missing multiplayer map: Castles
|
||||
* fixed wesnothd crashes
|
||||
* fixed clashing msg ids
|
||||
* code refactoring
|
||||
|
||||
Version 0.7.10:
|
||||
* help browser, hotkey is <F1>
|
||||
* new tabbed preferences dialog
|
||||
|
|
|
@ -332,6 +332,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Healing
|
||||
image=misc/item-healingpotion.png
|
||||
|
@ -361,6 +365,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Poison
|
||||
image=item-potion2.png
|
||||
|
@ -390,6 +398,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Holy Water
|
||||
image=misc/item-holywater.png
|
||||
|
@ -420,6 +432,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Strong
|
||||
image=item-potion3.png
|
||||
|
@ -455,6 +471,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Decay
|
||||
image=item-potion4.png
|
||||
|
@ -484,6 +504,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Ring of Regeneration
|
||||
image=item-ring1.png
|
||||
|
@ -519,6 +543,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Ring of Slowness
|
||||
image=item-ring2.png
|
||||
|
@ -548,6 +576,10 @@ What would you like to wish for?"
|
|||
y={Y}
|
||||
[/filter]
|
||||
[object]
|
||||
[filter]
|
||||
x={X}
|
||||
y={Y}
|
||||
[/filter]
|
||||
id={ID}
|
||||
name=Staff of Swiftness
|
||||
image=misc/item-staff.png
|
||||
|
@ -585,6 +617,7 @@ What would you like to wish for?"
|
|||
cannot_use_message="Only the mermen can use this item!"
|
||||
[filter]
|
||||
type=Merman,Merman Lord,Triton
|
||||
x,y={X},{Y}
|
||||
[/filter]
|
||||
[effect]
|
||||
apply_to=new_attack
|
||||
|
@ -633,6 +666,7 @@ What would you like to wish for?"
|
|||
cannot_use_message="Only the leader of an army can wield this sword!"
|
||||
[filter]
|
||||
description=Konrad
|
||||
x,y={X},{Y}
|
||||
[/filter]
|
||||
[effect]
|
||||
apply_to=new_attack
|
||||
|
@ -668,6 +702,11 @@ What would you like to wish for?"
|
|||
[/filter]
|
||||
[object]
|
||||
|
||||
[filter]
|
||||
type=Princess,Commander,Lord
|
||||
x,y={X},{Y}
|
||||
[/filter]
|
||||
|
||||
id={ID}
|
||||
|
||||
name=Sceptre of Fire
|
||||
|
@ -680,12 +719,6 @@ What would you like to wish for?"
|
|||
|
||||
cannot_use_message="This is the Sceptre of Fire. Only a true successor to the throne can possibly dare to take this!"
|
||||
|
||||
[filter]
|
||||
|
||||
type=Princess,Commander,Lord
|
||||
|
||||
[/filter]
|
||||
|
||||
[effect]
|
||||
|
||||
apply_to=new_attack
|
||||
|
|
|
@ -42,7 +42,7 @@ id=era_default
|
|||
music="wesnoth-4.ogg"
|
||||
terrain_liked=fwc
|
||||
[ai]
|
||||
recruitment_pattern=fighter,fighter,scout
|
||||
recruitment_pattern=fighter,fighter,fighter,archer,archer,scout
|
||||
[/ai]
|
||||
[/multiplayer_side]
|
||||
|
||||
|
@ -117,7 +117,7 @@ id=era_classic
|
|||
music="elf-land.ogg"
|
||||
terrain_liked=fwc
|
||||
[ai]
|
||||
recruitment_pattern=fighter,fighter,scout
|
||||
recruitment_pattern=fighter,fighter,fighter,archer,archer,scout
|
||||
[/ai]
|
||||
[/multiplayer_side]
|
||||
|
||||
|
@ -192,7 +192,7 @@ id=era_heroes
|
|||
music="wesnoth-4.ogg"
|
||||
terrain_liked=fwc
|
||||
[ai]
|
||||
recruitment_pattern=fighter,fighter,scout
|
||||
recruitment_pattern=fighter,fighter,fighter,archer,archer,scout
|
||||
[/ai]
|
||||
[/multiplayer_side]
|
||||
|
||||
|
|
|
@ -373,22 +373,27 @@ role={R}
|
|||
#some talking
|
||||
[message]
|
||||
description=King Dra-Nak
|
||||
id=msg_cmpgn_ei_14_01
|
||||
message="Why have you entered my lands?!?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_02
|
||||
message="We were traveling-"
|
||||
[/message]
|
||||
[message]
|
||||
description=King Dra-Nak
|
||||
id=msg_cmpgn_ei_14_03
|
||||
message="Silence! Did I ask you?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_14_04
|
||||
message="Um..yes."
|
||||
[/message]
|
||||
[message]
|
||||
description=King Dra-Nak
|
||||
id=msg_cmpgn_ei_14_05
|
||||
message="Shut up! Thats it! I'm putting you in the high-security cave!"
|
||||
[/message]
|
||||
|
||||
|
@ -405,18 +410,22 @@ role={R}
|
|||
#Gweddry talks to himself
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_06
|
||||
message="Ugh..."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_07
|
||||
message="Huh? Where am I?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_08
|
||||
message="It looks like I'm in some sort of prison..."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_09
|
||||
message="I think I will have to escape, and rescue Dacyn and Owaec."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -442,10 +451,12 @@ find_vacant=yes
|
|||
{TRUEUNSTORE 4-6 16-18 O}
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_10
|
||||
message="So you are in this cell! Come on, we have to escape!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_14_11
|
||||
message="Very well. I think the rest of the cells are further down this path."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -456,6 +467,7 @@ find_vacant=yes
|
|||
{TRUEUNSTORE 6-8 12-14 R2}
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_12
|
||||
message="So, they must have captured $R2.user_description in addition to Dacyn, Owaec and me. Well, $R2.type, follow me. We have to get out of this dungeon."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -466,6 +478,7 @@ find_vacant=yes
|
|||
{TRUEUNSTORE 6-8 8-10 R1}
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_13
|
||||
message=" It is nice to have a $R1.type among us! My guess is $R1.user_description will be able to shoot these devils without them doing anything about it, since most orcs are melee."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -476,18 +489,22 @@ find_vacant=yes
|
|||
{TRUEUNSTORE 6-8 4-6 D}
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_14
|
||||
message="Dacyn! Good, now we can try to escape. Do you know any way to get out?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_14_15
|
||||
message="No, but I think I can be of some help. I think I have found out where the key to the door is!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_16
|
||||
message="Really? Where?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_14_17
|
||||
message="The wall of the northern part of my cell, and right outside of it, is thinner than everywhere else. I think there isa hidden door there. Come, let us see!"
|
||||
[/message]
|
||||
[set_variable]
|
||||
|
@ -530,6 +547,7 @@ find_vacant=yes
|
|||
[then]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_18
|
||||
message="Here is the thin spot. Actually- wait a second- its not a thin spot at all! Its really a door!"
|
||||
[/message]
|
||||
[terrain]
|
||||
|
@ -539,6 +557,7 @@ find_vacant=yes
|
|||
{GUARD 3 3 (Troll Warrior)}
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_14_19
|
||||
message="Huh! A guard. Lets see how quickly we can kill it."
|
||||
[/message]
|
||||
[item]
|
||||
|
@ -561,6 +580,7 @@ find_vacant=yes
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_14_20
|
||||
message="I have found the key! Lets get out of here!"
|
||||
[/message]
|
||||
[set_variable]
|
||||
|
@ -586,6 +606,7 @@ find_vacant=yes
|
|||
[then]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_21
|
||||
message="This is the right key! Lets open the door, quick!"
|
||||
[/message]
|
||||
[terrain]
|
||||
|
@ -610,10 +631,12 @@ find_vacant=yes
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_14_22
|
||||
message=The high security prisoners are escaping!
|
||||
[/message]
|
||||
[message]
|
||||
description=King Dra-Nak
|
||||
id=msg_cmpgn_ei_14_23
|
||||
message=Kill them.
|
||||
[/message]
|
||||
#these are prisoners even though the macro is called PRISON
|
||||
|
@ -639,10 +662,12 @@ find_vacant=yes
|
|||
#a prisoner says something
|
||||
[message]
|
||||
speaker=narrator
|
||||
id=msg_cmpgn_ei_14_24
|
||||
message="The guards are distracted! Now is the time to escape!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_25
|
||||
message="What the...? Who said that?"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -666,14 +691,17 @@ find_vacant=yes
|
|||
{PRISON 32 19}
|
||||
[message]
|
||||
description=Valand
|
||||
id=msg_cmpgn_ei_14_26
|
||||
message="The guards are planning to execute us tomorrow! Please help us!"
|
||||
[/message]
|
||||
[message]
|
||||
x,y=34,20
|
||||
id=msg_cmpgn_ei_14_27
|
||||
message="Hah! Tomorrow? You make a big mistake if you believe you will live that long."
|
||||
[/message]
|
||||
[message]
|
||||
x,y=30,20
|
||||
id=msg_cmpgn_ei_14_28
|
||||
message="Right, boss, especially since they're invading, and we need to kill them now before they escape!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -688,6 +716,7 @@ find_vacant=yes
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_14_29
|
||||
message="Argh! Oh well, at least my vast hordes will defeat you!"
|
||||
[/message]
|
||||
{GUARD 20 10 (Orcish Grunt)}
|
||||
|
@ -712,6 +741,7 @@ find_vacant=yes
|
|||
[/filter]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_14_30
|
||||
message="Good! We have escaped these accursed caves, and can reunite with our army!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -725,6 +755,7 @@ find_vacant=yes
|
|||
name=victory
|
||||
[message]
|
||||
description=Valand
|
||||
id=msg_cmpgn_ei_14_31
|
||||
message="Thank you for rescuing me! I will help you on your quest, whatever it is."
|
||||
[/message]
|
||||
[/event]
|
||||
|
|
|
@ -87,34 +87,42 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_09_01
|
||||
message="We have come to a great river. What should we do? Should we attempt to cross it?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_09_02
|
||||
message="We must cross this river. The undead are chasing us. Reinforcements for the undead will arrive soon. we must be across the river before that happens."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_09_03
|
||||
message="Across this river lies the Northland. If we can get there, we may be able to get some ogres to help us."
|
||||
[/message]
|
||||
[message]
|
||||
description=Grug
|
||||
id=msg_cmpgn_ei_09_04
|
||||
message="Grug say we no help you! We finish must battle orc with!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Draka-Kura
|
||||
id=msg_cmpgn_ei_09_05
|
||||
message="And in Wesnothish that means?..."
|
||||
[/message]
|
||||
[message]
|
||||
description=Grug
|
||||
id=msg_cmpgn_ei_09_06
|
||||
message="Orc foolish! Die you now!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_09_07
|
||||
message="I think the ogres are trying to kill the orcs."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_09_08
|
||||
message="If we show ourselves as enemies of the orcs, they may help us. But I think we should cross the river before trying to convince these ogres to help."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -164,6 +172,7 @@ letter=C
|
|||
[/unit]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_09_09
|
||||
message="The undead reinforcements have arrived! We must cross the river immediately!"
|
||||
[/message]
|
||||
[terrain]
|
||||
|
@ -182,10 +191,12 @@ letter=C
|
|||
[then]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_09_10
|
||||
message="Good! We have crossed. Now let's see if we can get the Ogres to join us. They have been convinced to work for the Crown in the past; maybe it can be done again."
|
||||
[/message]
|
||||
[message]
|
||||
description=Grug
|
||||
id=msg_cmpgn_ei_09_11
|
||||
message="Grug say join you maybe he."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -196,6 +207,7 @@ letter=C
|
|||
[else]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_09_12
|
||||
message="Hurry up. We need to get across before these undead slaughter us!"
|
||||
[/message]
|
||||
[set_variable]
|
||||
|
|
|
@ -75,14 +75,17 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Volas
|
||||
id=msg_cmpgn_ei_04_01
|
||||
message="Greetings, travelers! Welcome to my realm."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_04_02
|
||||
message="Hello. I am wondering if you can help he fight these undead beasts that attack us."
|
||||
[/message]
|
||||
[message]
|
||||
description=Volas
|
||||
id=msg_cmpgn_ei_04_03
|
||||
message="Certainly. Although we will not leave our forests, we will help you reach the northern outpost, where the Lieutenant stationed there may aid you."
|
||||
[/message]
|
||||
|
||||
|
@ -103,18 +106,22 @@ Defeat:
|
|||
|
||||
[message]
|
||||
description=Gruga-Har
|
||||
id=msg_cmpgn_ei_04_04
|
||||
message="Intruders!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Volas
|
||||
id=msg_cmpgn_ei_04_05
|
||||
message="What? Those pesky orcs! They are the intruders, not us!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_04_06
|
||||
message="They are right in the Northern Path. We will have to fight them to move on."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gruga-Har
|
||||
id=msg_cmpgn_ei_04_07
|
||||
message="Bring forth the assassins, we may be able to poison them!"
|
||||
[/message]
|
||||
|
||||
|
@ -138,11 +145,13 @@ Defeat:
|
|||
|
||||
[message]
|
||||
description=Nafga
|
||||
id=msg_cmpgn_ei_04_08
|
||||
message="Your Warlordship, I am the only assassin left! Do you want me to go poison their leader?"
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
description=Gruga-Har
|
||||
id=msg_cmpgn_ei_04_09
|
||||
message="Perfect! Go, into the forest!"
|
||||
[/message]
|
||||
|
||||
|
@ -160,6 +169,7 @@ Defeat:
|
|||
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_04_10
|
||||
message="They have sent an assassin into the forest. We will have to be careful, and make sure he does not come out and attack us unexpectedly."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -176,6 +186,7 @@ Defeat:
|
|||
|
||||
[message]
|
||||
description=Nafga
|
||||
id=msg_cmpgn_ei_04_11
|
||||
message="Hahaha! Nafga will kill the elves!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -188,11 +199,13 @@ Defeat:
|
|||
|
||||
[message]
|
||||
description=Nafga
|
||||
id=msg_cmpgn_ei_04_12
|
||||
message="No! This is the first time I have failed a mission, and it is my last!"
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
description=Gruga-Har
|
||||
id=msg_cmpgn_ei_04_13
|
||||
message="My assassin is dead! the elves must pay, not for his death, but for stopping him in his mission!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
|
|
@ -89,10 +89,12 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_02_01
|
||||
message="Where are we? I cannot see where we are going."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_02_02
|
||||
message="I do not know. There are trolls in here, which may try to fight us."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -113,6 +115,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=narrator
|
||||
id=msg_cmpgn_ei_02_03
|
||||
message=The sign says 'Dead End'
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -125,14 +128,17 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_02_04
|
||||
message="Who goes there?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_02_05
|
||||
message="We are travelers loyal to the king of Wesnoth. Will you help us escape these trolls?"
|
||||
[/message]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_02_06
|
||||
message="Yes, we will help you, for although we have no loyalty to Wesnoth, we believe that you are on a noble quest."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -188,6 +194,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_02_07
|
||||
message="There is a great fortune in this chest of treasure! I can count two hundred pieces of gold!"
|
||||
[/message]
|
||||
[gold]
|
||||
|
@ -229,10 +236,12 @@ Defeat:
|
|||
#endif
|
||||
[message]
|
||||
description=Mal-Bakral
|
||||
id=msg_cmpgn_ei_02_08
|
||||
message="We have found you, human- Prepare to die!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_02_09
|
||||
message="They follow us. We must move quickly!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -245,8 +254,8 @@ Defeat:
|
|||
description=Gweddry
|
||||
[/filter]
|
||||
[message]
|
||||
id=lmsg2_3
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_02_10
|
||||
message="We have reached the end of the escape tunnel. I see daylight above us."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -77,18 +77,22 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_13_01
|
||||
message="The trail stops soon. Look at this- mountains block our path."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_13_02
|
||||
message="None of our troops can go on this harsh terrain. We must turn back!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_13_03
|
||||
message="If I remember correctly, there is a lake coming up here, with a bridge across it. It is the only way to get across the mountains."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_13_04
|
||||
message="Then let us go. Onward!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -102,6 +106,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_13_05
|
||||
message="This bridge is kind of rickety..."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -115,6 +120,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
speaker=unit
|
||||
id=msg_cmpgn_ei_13_06
|
||||
message="This bridge is going to collapse soon! Quick, across the river!"
|
||||
[/message]
|
||||
[set_variable]
|
||||
|
@ -143,6 +149,7 @@ Defeat:
|
|||
[/terrain]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_13_07
|
||||
message="Ah! The bridge collapsed!"
|
||||
[/message]
|
||||
[if]
|
||||
|
@ -154,12 +161,14 @@ Defeat:
|
|||
[then]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_13_08
|
||||
message="Everyone who is across the river, onward! Everyone else, try to go around the lake!"
|
||||
[/message]
|
||||
[/then]
|
||||
[else]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_13_09
|
||||
message="What? Now there is no way across! We will have to go around the lake."
|
||||
[/message]
|
||||
[/else]
|
||||
|
@ -190,6 +199,7 @@ y=$y1
|
|||
[/filter]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_13_10
|
||||
message="Good! We have made it to the end if the road. We can now get out of these mountains."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -108,21 +108,25 @@ Defeat:
|
|||
name=start
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_07_01
|
||||
message="We have came all the way to Mal-Ravanal's Capital!"
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_07_02
|
||||
message="Yes, but look! The undead forces are closing in behind us. We cannot kill Mal-Ravanal. We must turn back!"
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_07_03
|
||||
message="True. We must kill one of these necromancers that follows us to retreat. Still, I think we have done some good here: these enemies are delayed by our actions."
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_07_04
|
||||
message="These humans have dared to come this far into my land. Crush them!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -139,6 +143,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_07_05
|
||||
message="You dare to attack ME?!? Go back to your master!"
|
||||
[/message]
|
||||
[teleport]
|
||||
|
@ -215,22 +220,27 @@ Defeat:
|
|||
[/unit]
|
||||
[message]
|
||||
description=Terraent
|
||||
id=msg_cmpgn_ei_07_06
|
||||
message="Thank you for destroying that skeleton warrior! Every time you kill one of the advanced skeletons, one of my ally knights is let free!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_07_07
|
||||
message="Why? Are you the undead's prisoners?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Terraent
|
||||
id=msg_cmpgn_ei_07_08
|
||||
message="Yes. My allies and I were questing when we were ambushed by undead. The guard is playing a sick game- whenever one of their warriors dies, one of us is let free, but whenever you lose a fighter, they kill one of us."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_07_09
|
||||
message= "This sounds like a dangerous game. We will try to free as many of you as possible before we escape from here."
|
||||
[/message]
|
||||
[message]
|
||||
description=Terraent
|
||||
id=msg_cmpgn_ei_07_10
|
||||
message="There are five of us still locked up in the jail. All of us will join you if you can get us free."
|
||||
[/message]
|
||||
[/else]
|
||||
|
|
|
@ -143,22 +143,27 @@ y={Y}
|
|||
[/recall]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_06_01
|
||||
message="Hail, Gweddry!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_06_02
|
||||
message="Hello. We have been forced from our positions. Do you think you can help us regain our outpost?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_06_03
|
||||
message="I am not sure. There are bandits in this country, and it is they who rule this land, not the king. My men are afraid of them, and refuse to come out and fight. As you see, though I have many men, they stay penned up in the keep. The thieves hide in the villages."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_06_04
|
||||
message="We will see if we can get across to where you are without thieves killing us. Also, we will try to go to the villages and drive the thieves out. Onward, men!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Raklar
|
||||
id=msg_cmpgn_ei_06_05
|
||||
message="Stop these intruders from getting through. Ambush them!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -203,14 +208,17 @@ y={Y}
|
|||
[then]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_06_06
|
||||
message="We have defeated these bandits. Perhaps, now that we are here, Owaec's troops will not be afraid to exit his castle."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_06_07
|
||||
message="Yes, hopefully. Our outpost has been overrun by undead. What about yours? Have you encountered them?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_06_08
|
||||
message="No, I have not encountered any undead yet. However, I don't think me and my men can do any more good here. We will come with you to see if, together, we cannot find a way to push back these undead."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -233,10 +241,12 @@ y={Y}
|
|||
[/unit]
|
||||
[message]
|
||||
description=Mal-Karhal
|
||||
id=msg_cmpgn_ei_06_09
|
||||
message="Hahaha! I have found you, pesky humans! Prepare to die!"
|
||||
[/message]
|
||||
[message]
|
||||
discription=Owaec
|
||||
id=msg_cmpgn_ei_06_10
|
||||
message="Oh no! The undead have come, and we have not had time to prepare for them! We will all die now!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -75,14 +75,17 @@ y=10
|
|||
#endif
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_11_01
|
||||
message="Look, we have found a pack of Ogres. Lets see if we can capture some to train."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_11_02
|
||||
message="Alright, we have to keep at least two of these Ogres on the grass until our troops get here to capture them."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_11_03
|
||||
message="We should try to surround them. Gweddry, you stay where you are. Dacyn, you go north-east. I'll go north-west."
|
||||
[/message]
|
||||
[teleport]
|
||||
|
@ -116,6 +119,7 @@ y=10
|
|||
[/filter]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_11_04
|
||||
message="We have let one escape. Lets hope they all don't!"
|
||||
[/message]
|
||||
[kill]
|
||||
|
@ -141,6 +145,7 @@ y=10
|
|||
[then]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_11_05
|
||||
message="Good! We have managed to capture some Ogres. We can now recruit them into our army."
|
||||
[/message]
|
||||
[allow_recruit]
|
||||
|
@ -150,6 +155,7 @@ y=10
|
|||
[else]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_11_06
|
||||
message="We didn't capture enough of the ogres here. We will have to go on without them."
|
||||
[/message]
|
||||
[/else]
|
||||
|
|
|
@ -110,18 +110,22 @@ aggression=0.6
|
|||
name=start
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_01_01
|
||||
message="Come, brothers, let us destroy these humans that stop us from entering Wesnoth!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Sakkat
|
||||
id=msg_cmpgn_ei_01_02
|
||||
message="Since we have no will of our own, we must agree with you."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_01_03
|
||||
message="No! We must hold this outpost!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_01_04
|
||||
message="Sir, we cannot hold out forever. I am going to search the castle and see if there is any way we can escape and warn the King."
|
||||
[/message]
|
||||
[kill]
|
||||
|
@ -141,6 +145,7 @@ aggression=0.6
|
|||
[/unit]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_01_05
|
||||
message="Sir! We can escape from here now! I have found a trapdoor next to the castle!"
|
||||
[/message]
|
||||
|
||||
|
@ -159,6 +164,7 @@ aggression=0.6
|
|||
[/filter]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_01_06
|
||||
message="Follow me, men! Through the trapdoor!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -173,6 +179,7 @@ aggression=0.6
|
|||
name= turn 14
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_01_07
|
||||
message="Hurry! Before long enemy reinforcements will arrive, and we will all die! Come to the trapdoor!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -188,6 +195,7 @@ aggression=0.6
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_01_08
|
||||
message="You dare to attack ME?!? Go back to your master!"
|
||||
[/message]
|
||||
[teleport]
|
||||
|
|
|
@ -79,54 +79,67 @@
|
|||
[/recall]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_12_01
|
||||
message="Hail, Dwarves! Will you help us defeat these foul Orcs?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Prok-Bak
|
||||
id=msg_cmpgn_ei_12_02
|
||||
message="You human! Call us foul, will you?!?!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Pelathsil
|
||||
id=msg_cmpgn_ei_12_03
|
||||
message="Why should we help you? You're not a dwarf!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_12_04
|
||||
message="Your people helped us in the past, in the tunnels in the South. Why won't you help us now?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Pelathsil
|
||||
id=msg_cmpgn_ei_12_05
|
||||
message="Impossible! I can't believe any of my comrades would have helped a human!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Elandin
|
||||
id=msg_cmpgn_ei_12_06
|
||||
message="Indeed. Why should any of us help those not in our tribe?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_12_07
|
||||
message="Will you at least let us pass in safety?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Elandin
|
||||
id=msg_cmpgn_ei_12_08
|
||||
message="I am afraid that is now impossible."
|
||||
[/message]
|
||||
[message]
|
||||
description=Prok-Bak
|
||||
id=msg_cmpgn_ei_12_09
|
||||
message="Orcs, kill'em all! Humans, elves or dwarves, it don't matter!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Elandin
|
||||
id=msg_cmpgn_ei_12_10
|
||||
message="These orcs will die. But so will you, human. You have tresspassed on Elvish land."
|
||||
[/message]
|
||||
[message]
|
||||
description=Pelathsil
|
||||
id=msg_cmpgn_ei_12_11
|
||||
message="Oh, elvish land is it now? Die, you elf-dog! And you too, human!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_12_12
|
||||
message="These people won't listen to reason, they are blinded by their own races supposed superiority!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_12_13
|
||||
message="True. As much as I dislike killing anything that is not evil, it seems we will have to kill these elves, and these dwarves, before they kill us."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -147,6 +160,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Pelathsil
|
||||
id=msg_cmpgn_ei_12_14
|
||||
message="Argh! I'm dead! well, dwarves are still the best!"
|
||||
[/message]
|
||||
[gold]
|
||||
|
@ -165,6 +179,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Prok-Bak
|
||||
id=msg_cmpgn_ei_12_15
|
||||
message="I die? Orcs rule all!"
|
||||
[/message]
|
||||
[gold]
|
||||
|
@ -183,6 +198,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Elandin
|
||||
id=msg_cmpgn_ei_12_16
|
||||
message="It seems these darn humans are more powerful than I though. Ugh."
|
||||
[/message]
|
||||
[gold]
|
||||
|
|
|
@ -92,34 +92,42 @@ Defeat:
|
|||
name=start
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_08_01
|
||||
message="Look! The road splits here. Which way shall we go?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_08_02
|
||||
message="I know this area. I was here on an earlier patrol. Just north of here there is a river that leads to the northlands, where orcs live. To the east lies the mountains, then the undead lands."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_08_03
|
||||
message="We should probably go north to the orcish lands and try to circle around and catch the undead by suprise."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_08_04
|
||||
message="No, I think we should go straight into the undead lands. Strike hard and fast!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_08_05
|
||||
message="Either way we will have to fight. Look, the orcs and undead are fighting each other, and block our path!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Arnai
|
||||
id=msg_cmpgn_ei_08_06
|
||||
message="Well, orc, we can either continue this fight, or we can crush there pesky humans and battle later. Your call."
|
||||
[/message]
|
||||
[message]
|
||||
description=Wak-Rano
|
||||
id=msg_cmpgn_ei_08_07
|
||||
message="Hm... I know. We will make a pact to destroy these humans, and continue our fight later. (hopefully you will die, for then I will win our battle by default.)"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Arnai
|
||||
id=msg_cmpgn_ei_08_08
|
||||
message="Very well, we are allies, for now. (this foolish orc will surely die)."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -131,6 +139,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Wak-Rano
|
||||
id=msg_cmpgn_ei_08_09
|
||||
message="No! These undead has won our battle, and you will be able to enter my northern homeland!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -147,6 +156,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Arnai
|
||||
id=msg_cmpgn_ei_08_10
|
||||
message="You have entered my master's country! He will not be pleased about this."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -74,14 +74,17 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_05_01
|
||||
message="We have reached the borders of the undead land. Surely you do not mean to go forward- we will all die if we do! We should turn North and help Owaec, captain of the Northern Outpost, hold off the undead."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_05_02
|
||||
message="I am not yet sure. Whether we go forward or backward, we will have to fight. The necromancer Mal-Skraat has chased us."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_05_03
|
||||
message="They run from me! Still, it will not help them, the border patrol will destroy them. I may even be promoted!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -93,10 +96,12 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_05_04
|
||||
message="Now I will never get promoted!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_05_05
|
||||
message="Come, let us return to Wesnoth and aid the Northern Outpost."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -113,20 +118,25 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_05_06
|
||||
message="We have defeated this patrol, but we can still turn back! Do we want to go further into these lands now, or do we want to try to turn back and defeat this necromancer?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_05_07
|
||||
message="Hmm..."
|
||||
[option]
|
||||
id=msg_cmpgn_ei_05_08
|
||||
message="We do not want to waste time here fighting Mal-Skraat. Onward!"
|
||||
[command]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_05_09
|
||||
message="I will not say if this is a good decision, but I will follow you."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_05_10
|
||||
message="Noo!!! I can't be promoted if they run away!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -137,10 +147,12 @@ Defeat:
|
|||
[/command]
|
||||
[/option]
|
||||
[option]
|
||||
id=msg_cmpgn_ei_05_11
|
||||
message="You are right. It is foolish to go onward- we must defeat Mal-Skraat and turn back, going to the Northern Outpost."
|
||||
[command]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_05_12
|
||||
message="Good! if I defeat them, I can become a lich!"
|
||||
[/message]
|
||||
[/command]
|
||||
|
@ -157,6 +169,7 @@ Defeat:
|
|||
[then]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_05_13
|
||||
message="We failed to defeat either enemy! Now more lichs will come, and we will be overwhelmed!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -166,10 +179,12 @@ Defeat:
|
|||
[else]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_05_14
|
||||
message="We cannot spend any more time defeating Mal-Skraat. Like it or not, we must go further into these undead lands."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_05_15
|
||||
message="Noo!!! He will reach Mal-Ravanal's capital, and I shall be punished for letting him escape!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -61,18 +61,22 @@ Defeat:
|
|||
[/recall]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_10_01
|
||||
message="Look- here is a large river. Should we attempt to cross it, or turn back?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_10_02
|
||||
message="We must cross this river. It is said that Ogres live north of here, and we must enlist their aid if we are to defeat the undead. The undead realize this, that is why they have sent a Lich to block our path."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_10_03
|
||||
message="Across this river lies the Northland. Yes, Ogres live there, but so do Orcs, who will try to stop us. We should proceed with caution."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Karanad
|
||||
id=msg_cmpgn_ei_10_04
|
||||
message="I will leave your bodies to rot in the river, then I will raise you up to serve in my Master's undead hordes!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -89,6 +93,7 @@ y=13
|
|||
name=turn 10
|
||||
[message]
|
||||
description=Mal-Karanad
|
||||
id=msg_cmpgn_ei_10_05
|
||||
message="I summon from the depths of the river those beasts which will destroy you!"
|
||||
[/message]
|
||||
[scroll_to_unit]
|
||||
|
@ -117,6 +122,7 @@ y=13
|
|||
#endif
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_10_06
|
||||
message="It seems as if in addition to summoning undead this Lich has learned to call up demons!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
|
|
@ -98,34 +98,42 @@ Defeat:
|
|||
name=start
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_03_01
|
||||
message="We have escaped from those dark tunnels! But where are we now?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_03_02
|
||||
message="Oh no! We are in the middle of enemy territory!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Kallat
|
||||
id=msg_cmpgn_ei_03_03
|
||||
message="Hahaha! We have you surrounded!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_03_04
|
||||
message="Why don't we see if the new recruit can handle them. After all, there are only two!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Tar
|
||||
id=msg_cmpgn_ei_03_05
|
||||
message="No!!! They'll kill me!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Kallat
|
||||
id=msg_cmpgn_ei_03_06
|
||||
message="So? We don't care- you're only a Dark Adept."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_03_07
|
||||
message="It seems Mal-Tar is weak, but his brothers are still surrounding us. I propose we kill him and use his castle as a base for our attack!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_03_08
|
||||
message="If we kill Mal-Skraat, we will have opened a way to enter Wesnoth, but if we kill Mal-Kallat, we will be able to penetrate further into Undead lands."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -137,6 +145,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_03_09
|
||||
message="No! You have defeated me, and can re-enter Wesnoth!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -153,6 +162,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
description=Mal-Skraat
|
||||
id=msg_cmpgn_ei_03_10
|
||||
message="You have defeated my brother, but I will follow you and kill you!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -221,38 +221,47 @@ y={Y}
|
|||
#endif
|
||||
[message]
|
||||
description=Konrad II
|
||||
id=msg_cmpgn_ei_15_01
|
||||
message="Welcome to Weldyn, Gweddry! Unfortunately we cannot give you as great a welcome as you deserve."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_15_02
|
||||
message="Thank you, my King Konrad II."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_03
|
||||
message="Well, yes, us being here is all well and good, but there are undead hordes pressing up against our gates. Now what are we going to do about that?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_15_04
|
||||
message="We need to fight them. Look, night approaches- they will soon attack. I hope we can hold them off."
|
||||
[/message]
|
||||
[message]
|
||||
description=Konrad III
|
||||
id=msg_cmpgn_ei_15_05
|
||||
message="I will hold my gate. With my quick and skillful warriors I can resist the undead, at least for a while."
|
||||
[/message]
|
||||
[message]
|
||||
description=Garard III
|
||||
id=msg_cmpgn_ei_15_06
|
||||
message="Yes, and my people may be slow, but their blows are the most powerful of all. I can hold my post."
|
||||
[/message]
|
||||
[message]
|
||||
description=Haldric IX
|
||||
id=msg_cmpgn_ei_15_07
|
||||
message="Archers are the most powerful fighters of all, as they shall prove in the upcoming battle."
|
||||
[/message]
|
||||
[message]
|
||||
description=Konrad II
|
||||
id=msg_cmpgn_ei_15_08
|
||||
message="Peace, my sons! We are fighting the enemy, there is no need for rivalry within our camp."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_09
|
||||
message="In any case, the undead are attacking now. Let us hope we can last out the night."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -264,10 +273,12 @@ y={Y}
|
|||
[/filter]
|
||||
[message]
|
||||
description=Garard III
|
||||
id=msg_cmpgn_ei_15_10
|
||||
message="No! These undead have defeated me!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Trakaax
|
||||
id=msg_cmpgn_ei_15_11
|
||||
message="And now we will revive you to serve us, as an undead Knight!"
|
||||
[/message]
|
||||
[unit]
|
||||
|
@ -280,6 +291,7 @@ y={Y}
|
|||
[/unit]
|
||||
[message]
|
||||
description=Garard III
|
||||
id=msg_cmpgn_ei_15_12
|
||||
message="Time to defeat these pesky humans, in my new body."
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -290,10 +302,12 @@ y={Y}
|
|||
[/filter]
|
||||
[message]
|
||||
description=Konrad III
|
||||
id=msg_cmpgn_ei_15_13
|
||||
message="No! I have been defeated! I only hope the undead do not raise me to fight against you!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Grekulak
|
||||
id=msg_cmpgn_ei_15_14
|
||||
message="Oh, don't worry, we will. Mwahahahahaha!!!"
|
||||
[/message]
|
||||
[unit]
|
||||
|
@ -306,6 +320,7 @@ y={Y}
|
|||
[/unit]
|
||||
[message]
|
||||
description=Konrad III
|
||||
id=msg_cmpgn_ei_15_15
|
||||
message="Well, my one-time father, let us see who will last out the night!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -314,22 +329,27 @@ y={Y}
|
|||
name=turn 9
|
||||
[message]
|
||||
description=Haldric IX
|
||||
id=msg_cmpgn_ei_15_16
|
||||
message="Its difficult to defeat these undead. It will be much easier to join them."
|
||||
[/message]
|
||||
[message]
|
||||
description=Konrad II
|
||||
id=msg_cmpgn_ei_15_17
|
||||
message="Huh?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Haldric IX
|
||||
id=msg_cmpgn_ei_15_18
|
||||
message="You idiot, I'm defecting!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_15_19
|
||||
message="You traitor!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Uknalu
|
||||
id=msg_cmpgn_ei_15_20
|
||||
message="Yes! Now my victory is assured!"
|
||||
[/message]
|
||||
[store_unit]
|
||||
|
@ -350,6 +370,7 @@ y={Y}
|
|||
[/gold]
|
||||
[message]
|
||||
description=Haldric IX
|
||||
id=msg_cmpgn_ei_15_21
|
||||
message="Come, my warriors, let us defeat this foolish King!"
|
||||
[/message]
|
||||
[role]
|
||||
|
@ -359,6 +380,7 @@ y={Y}
|
|||
[/role]
|
||||
[message]
|
||||
speaker=loyal
|
||||
id=msg_cmpgn_ei_15_22
|
||||
message="I don't think so! Our loyalty is with the King!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -370,10 +392,12 @@ y={Y}
|
|||
[/filter]
|
||||
[message]
|
||||
description=Konrad II
|
||||
id=msg_cmpgn_ei_15_23
|
||||
message="I have died, and with me the city shall fall."
|
||||
[/message]
|
||||
[message]
|
||||
description=Haldric IX
|
||||
id=msg_cmpgn_ei_15_24
|
||||
message="Now I shall be the king of the undead Wesnoth!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -385,6 +409,7 @@ y={Y}
|
|||
name=time over
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_25
|
||||
message="Look, the sun has risen. The undead are retreating."
|
||||
[/message]
|
||||
[unit]
|
||||
|
@ -396,70 +421,87 @@ y={Y}
|
|||
[/unit]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_26
|
||||
message="Well, you have defeated some of my captains. Good job. But that was only a small fraction of my horde."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_27
|
||||
message="What is your point?"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_28
|
||||
message="Well, it would be very easy for me to defeat you. But I don't think it would do justice to my power."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_15_29
|
||||
message="We don't care about honoring your power. Bring it on!"
|
||||
[/message]
|
||||
[message]
|
||||
decription=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_30
|
||||
message="Shut up, fool. I meant my own power, not the power of my legions. And that brings me to my second point. You, Gweddry, as a commander, are a coward."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_15_31
|
||||
message="What, me, a coward!?! Why!?!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_32
|
||||
message="Yes, you, a coward. You claim to have defeated my captains, but it was really your hordes, not you."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_33
|
||||
message="Hordes is a name used for undead. We prefer to call ourselves an army."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_34
|
||||
message="Silence, fool! The point is that Gweddry could not have defeated my minions without the help of his slaves!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_15_35
|
||||
message="I'm not a slave! And YOU'RE the fool!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_36
|
||||
message="SHUT UP! I doubt Gweddry could even last two seconds in actual combat. And I'll prove it. I challenge you, Gweddry, to a duel."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_15_37
|
||||
message="I'm not going to fight you in one-on-one combat!"
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_38
|
||||
message="That only proves you are a coward. Anyway, who said anything about one-on-one combat? I said a duel, six-on-six. Pick your five best slaves and I will pick my five best minions."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_15_39
|
||||
message="That is a very interesting notion of a duel. Gweddry, I suggest you accept, since he keeps calling you a coward."
|
||||
[/message]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_15_40
|
||||
message="No, don't accept. It is obviously a trick- he will bring many more than five people. We must win this battle on our own terms."
|
||||
[/message]
|
||||
[message]
|
||||
description=Mal-Ravanal
|
||||
id=msg_cmpgn_ei_15_41
|
||||
message="I'll make it simple. Accept, or face the onslaught of my hordes, like the coward that you are."
|
||||
[/message]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_15_42
|
||||
message=Hmm...
|
||||
[option]
|
||||
name="I'll accept this duel, and prove I am not a coward once and for all."
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
[/filter]
|
||||
[message]
|
||||
description=Gweddry
|
||||
id=msg_cmpgn_ei_death_gweddry
|
||||
message="No! I have failed in my mission to save Wesnoth from destruction!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -19,6 +20,7 @@
|
|||
[/filter]
|
||||
[message]
|
||||
description=Dacyn
|
||||
id=msg_cmpgn_ei_death_dacyn
|
||||
message="Wesnoth is doomed! Without me, Gweddry has no hope!"
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
@ -33,10 +35,12 @@
|
|||
[/filter]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_death_owaec1
|
||||
message="My outpost has fallen..."
|
||||
[/message]
|
||||
[message]
|
||||
description=Owaec
|
||||
id=msg_cmpgn_ei_death_owaec2
|
||||
message="ugh."
|
||||
[/message]
|
||||
[endlevel]
|
||||
|
|
|
@ -167,12 +167,12 @@ Defeat:
|
|||
[command]
|
||||
[message]
|
||||
description=Konrad
|
||||
id=msg11_4
|
||||
id=msg11_5e
|
||||
message="This old mine seems to be connected to the main tunnels."
|
||||
[/message]
|
||||
[message]
|
||||
description=Kalenz
|
||||
id=msg11_5b
|
||||
id=msg11_5f
|
||||
message="I am hesitant to enter. It will be so difficult in the darkness!"
|
||||
[/message]
|
||||
[message]
|
||||
|
|
|
@ -171,7 +171,7 @@ simple_targetting=yes
|
|||
canrecruit=1
|
||||
recruit=Elvish Fighter,Elvish Archer,Elvish Ranger
|
||||
[ai]
|
||||
recruitment_pattern=fighter,archer
|
||||
recruitment_pattern=fighter,archer,mixed fighter
|
||||
[/ai]
|
||||
gold=200
|
||||
team_name=elves
|
||||
|
@ -184,7 +184,7 @@ simple_targetting=yes
|
|||
canrecruit=1
|
||||
recruit=Elvish Shaman,Elvish Archer,Elvish Fighter
|
||||
[ai]
|
||||
recruitment_pattern=archer,fighter
|
||||
recruitment_pattern=archer,archer,fighter,fighter,healer
|
||||
[/ai]
|
||||
gold=200
|
||||
team_name=elves
|
||||
|
|
|
@ -206,7 +206,7 @@ Defeat:
|
|||
message="What is that?"
|
||||
[/message]
|
||||
[message]
|
||||
id=msg9_a4
|
||||
id=msg9_a3
|
||||
description=Kalenz
|
||||
message="Creatures of the deep are upon us! This may be very dangerous. Be quick! We must get to the other side with all haste!"
|
||||
[/message]
|
||||
|
|
|
@ -335,14 +335,14 @@ Defeat:
|
|||
[message]
|
||||
id=hasty_15
|
||||
speaker=narrator
|
||||
message="You receive 500 pieces of gold!"
|
||||
message="You receive 200 pieces of gold!"
|
||||
[/message]
|
||||
[/command]
|
||||
|
||||
[command]
|
||||
[gold]
|
||||
side=1
|
||||
amount=500
|
||||
amount=200
|
||||
[/gold]
|
||||
[/command]
|
||||
|
||||
|
|
|
@ -413,16 +413,16 @@ Defeat
|
|||
[/command]
|
||||
[command]
|
||||
[message]
|
||||
id=msg12_27
|
||||
id=msg12_27a
|
||||
description=Geldar
|
||||
message="You are right, friend. I will put my best men at your disposal. We know not where the Scepter is though. Legend says it is hidden in the northern tunnels."
|
||||
message="You are right, friend. I will put my best men at your disposal. We know not where the Scepter is though. Legend says it is hidden in the eastern tunnels."
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
[message]
|
||||
id=msg12_28
|
||||
id=msg12_28a
|
||||
description=Delfador
|
||||
message="Then to the northern tunnels we shall go!"
|
||||
message="Then to the eastern tunnels we shall go!"
|
||||
[/message]
|
||||
[/command]
|
||||
[command]
|
||||
|
|
|
@ -11,7 +11,7 @@ next_scenario=A_Choice_Must_Be_Made
|
|||
name=The Sceptre of Fire
|
||||
id=Sceptre
|
||||
map_data="{maps/Heir_To_The_Throne/Sceptre}"
|
||||
turns=60
|
||||
turns=40
|
||||
victory_when_enemies_defeated=no
|
||||
|
||||
{UNDERGROUND}
|
||||
|
@ -113,7 +113,7 @@ Defeat:
|
|||
recruit=Goblin Knight,Wolf Rider,Troll,Orcish Warrior,Orcish Crossbow
|
||||
team_name=orcs
|
||||
|
||||
{GOLD 80 150 200}
|
||||
{GOLD 30 50 90}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
[/items]
|
||||
|
@ -149,7 +149,7 @@ Defeat:
|
|||
recruit=Troll,Troll Warrior,Ogre
|
||||
#endif
|
||||
team_name=orcs
|
||||
{GOLD 80 150 200}
|
||||
{GOLD 30 50 80}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
[/items]
|
||||
|
@ -196,11 +196,11 @@ Defeat:
|
|||
#ifdef EASY
|
||||
recruit=Troll,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
#else
|
||||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp,Saurian
|
||||
#endif
|
||||
team_name=orcs
|
||||
|
||||
{GOLD 80 150 200}
|
||||
{GOLD 30 60 120}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
[/items]
|
||||
|
@ -225,10 +225,10 @@ Defeat:
|
|||
#ifdef EASY
|
||||
recruit=Troll,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
#else
|
||||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp
|
||||
recruit=Troll,Troll Warrior,Ogre,Goblin Knight,Wolf Rider,Troll Whelp,Saurian
|
||||
#endif
|
||||
team_name=orcs
|
||||
{GOLD 80 150 200}
|
||||
{GOLD 40 70 150}
|
||||
{INCOME 5 10 20}
|
||||
[/side]
|
||||
[/items]
|
||||
|
|
|
@ -55,9 +55,9 @@ Defeat:
|
|||
canrecruit=1
|
||||
recruit=Orcish Warrior,Wolf Rider,Troll,Troll Whelp,Goblin Pillager
|
||||
#ifdef HARD
|
||||
gold=300
|
||||
gold=500
|
||||
#else
|
||||
gold=200
|
||||
gold=350
|
||||
#endif
|
||||
team_name=evil
|
||||
[/side]
|
||||
|
@ -284,7 +284,7 @@ Defeat:
|
|||
[/filter]
|
||||
[message]
|
||||
id=msg13_9d
|
||||
description=Konrad
|
||||
speaker=second_unit
|
||||
message="I did not know that the undead were in these pits!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
@ -350,9 +350,9 @@ Defeat:
|
|||
message="Rest in peace, Lionel. The poor, lost general."
|
||||
[/message]
|
||||
[message]
|
||||
id=msg13_die3
|
||||
id=msg13_die3a
|
||||
description=Lionel
|
||||
message="I am destroyed, but my mission must be completed. Though you are foes, you are at least worthy ones, so I will tell you that the Scepter is further north from here, deep in the caverns. May you have better fortune in your quest than I did!"
|
||||
message="I am destroyed, but my mission must be completed. Though you are foes, you are at least worthy ones, so I will tell you that the Scepter is east from here, the way you have come from, deep in the caverns. I made the mistake of not asking for directions when I became lost. May you have better fortune in your quest than I did!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
[multiplayer]
|
||||
name="Siege Castles"
|
||||
map=castles
|
||||
map_data="{maps/Multiplayer/Castles}"
|
||||
turns=90
|
||||
id=multiplayer_castles
|
||||
|
||||
|
|
|
@ -76,6 +76,25 @@
|
|||
{TERRAIN_BASE ~ fog}
|
||||
{TERRAIN_BASE ( ) void}
|
||||
|
||||
|
||||
#
|
||||
# Villages
|
||||
#
|
||||
|
||||
{TERRAIN_BASE Y swampwater}
|
||||
{BUILDING Y village-swampwater}
|
||||
{TERRAIN_BASE V snow}
|
||||
{BUILDING V village-snow}
|
||||
{TERRAIN_BASE Z coast}
|
||||
{BUILDING Z village-coast}
|
||||
{TERRAIN_BASE v grassland}
|
||||
{BUILDING v village-human}
|
||||
{TERRAIN_BASE D cave}
|
||||
{BUILDING D village-cave}
|
||||
{TERRAIN_BASE t grassland}
|
||||
{BUILDING t village}
|
||||
|
||||
|
||||
#
|
||||
# Transition between terrains
|
||||
#
|
||||
|
@ -135,24 +154,6 @@ K
|
|||
{TERRAIN_ADJACENT_1 s !s ocean}
|
||||
|
||||
|
||||
#
|
||||
# Villages
|
||||
#
|
||||
|
||||
{TERRAIN_BASE Y swampwater}
|
||||
{BUILDING Y village-swampwater}
|
||||
{TERRAIN_BASE V snow}
|
||||
{BUILDING V village-snow}
|
||||
{TERRAIN_BASE Z coast}
|
||||
{BUILDING Z village-coast}
|
||||
{TERRAIN_BASE v grassland}
|
||||
{BUILDING v village-human}
|
||||
{TERRAIN_BASE D cave}
|
||||
{BUILDING D village-cave}
|
||||
{TERRAIN_BASE t grassland}
|
||||
{BUILDING t village}
|
||||
|
||||
|
||||
|
||||
# Some test cases
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ width=800
|
|||
height=600
|
||||
|
||||
[main_map]
|
||||
rect=0,26,887,768
|
||||
rect=0,26,882,768
|
||||
xanchor=left
|
||||
yanchor=top
|
||||
[/main_map]
|
||||
|
@ -23,7 +23,7 @@ height=600
|
|||
[menu]
|
||||
title=main_menu
|
||||
image=lite
|
||||
items=speak,objectives,unitlist,recruit,recall,statustable,endturn,undo,redo,save,load,statistics,preferences,help,quit
|
||||
items=speak,objectives,unitlist,recruit,recall,statustable,endturn,undo,redo,save,load,statistics,preferences,chatlog,help,quit
|
||||
rect=3,1,100,22
|
||||
xanchor=fixed
|
||||
yanchor=fixed
|
||||
|
@ -60,24 +60,24 @@ height=600
|
|||
# rightside panel
|
||||
[panel]
|
||||
image=misc/rightside.png
|
||||
rect=887,24,1024,284
|
||||
rect=882,25,1024,309
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/panel]
|
||||
[mini_map]
|
||||
rect=900,32,1016,177
|
||||
rect=892,32,1017,175
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/mini_map]
|
||||
[panel]
|
||||
image=misc/rightside-bg.png
|
||||
rect=887,284,1024,768
|
||||
rect=882,309,1024,730
|
||||
xanchor=right
|
||||
yanchor=top
|
||||
[/panel]
|
||||
[panel]
|
||||
image=misc/rightside-bottom.png
|
||||
rect=887,713,0,768
|
||||
rect=882,730,0,768
|
||||
xanchor=right
|
||||
yanchor=bottom
|
||||
[/panel]
|
||||
|
@ -85,7 +85,7 @@ height=600
|
|||
[menu]
|
||||
title=action_endturn
|
||||
items=endturn
|
||||
rect=904,736
|
||||
rect=900,738
|
||||
xanchor=right
|
||||
yanchor=bottom
|
||||
[/menu]
|
||||
|
@ -127,6 +127,22 @@ height=600
|
|||
yanchor=fixed
|
||||
[/panel]
|
||||
|
||||
# HP/XP
|
||||
[label]
|
||||
font_size=10
|
||||
text=hp
|
||||
rect=967,234,1022,246
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/label]
|
||||
[label]
|
||||
font_size=10
|
||||
text=xp
|
||||
rect=967,260,1022,272
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/label]
|
||||
|
||||
# gold icon
|
||||
[label]
|
||||
icon=misc/gold.png
|
||||
|
@ -171,7 +187,7 @@ height=600
|
|||
[status]
|
||||
# the time of day image
|
||||
[time_of_day]
|
||||
rect=900,185,1017,225
|
||||
rect=892,184,1017,223
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/time_of_day]
|
||||
|
@ -254,25 +270,25 @@ height=600
|
|||
|
||||
#unit stats here
|
||||
[unit_image]
|
||||
rect=900,235,946,283
|
||||
rect=891,235,963,307
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_image]
|
||||
[unit_description]
|
||||
font_size=14
|
||||
rect=900,290,1020,308
|
||||
rect=891,312,1022,330
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_description]
|
||||
[unit_type]
|
||||
font_size=12
|
||||
rect=900,308,1020,324
|
||||
rect=891,330,1022,346
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_type]
|
||||
[unit_level]
|
||||
font_size=12
|
||||
rect=900,324,1020,340
|
||||
rect=891,346,1022,362
|
||||
prefix=level
|
||||
prefix_literal=" "
|
||||
xanchor=right
|
||||
|
@ -280,31 +296,32 @@ height=600
|
|||
[/unit_level]
|
||||
[unit_alignment]
|
||||
font_size=12
|
||||
rect=900,340,1020,356
|
||||
rect=891,362,1022,378
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_alignment]
|
||||
[unit_traits]
|
||||
font_size=12
|
||||
rect=900,356,1020,372
|
||||
rect=891,378,1022,394
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_traits]
|
||||
[unit_abilities]
|
||||
font_size=12
|
||||
rect=900,372,1020,388
|
||||
rect=891,394,1022,410
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_abilities]
|
||||
[unit_status]
|
||||
font_size=12
|
||||
rect=958,241,1008,291
|
||||
#rect=958,241,1008,291
|
||||
rect=968,289,1020,305
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_status]
|
||||
[unit_moves]
|
||||
font_size=12
|
||||
rect=900,404,1020,420
|
||||
rect=891,410,1022,426
|
||||
prefix=movement
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
|
@ -312,23 +329,28 @@ height=600
|
|||
[/unit_moves]
|
||||
[unit_hp]
|
||||
font_size=12
|
||||
rect=900,420,1020,436
|
||||
prefix=hp
|
||||
prefix_literal=": "
|
||||
rect=967,246,1022,260
|
||||
#prefix=hp
|
||||
#prefix_literal=" "
|
||||
#prefix=""
|
||||
#prefix_literal=""
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_hp]
|
||||
[unit_xp]
|
||||
font_size=12
|
||||
rect=900,436,1020,452
|
||||
prefix=xp
|
||||
prefix_literal=": "
|
||||
rect=967,272,1022,286
|
||||
#prefix=xp
|
||||
#prefix_literal=" "
|
||||
#prefix=""
|
||||
#prefix_literal=""
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_xp]
|
||||
[unit_weapons]
|
||||
font_size=12
|
||||
rect=900,452,1020,620
|
||||
#rect=900,452,1020,620
|
||||
rect=891,426,1022,594
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_weapons]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[mask]
|
||||
name=castle-convex-ne
|
||||
image=mask-castle-ne.png
|
||||
shift=-18,-45
|
||||
shift=-18,-36
|
||||
[/mask]
|
||||
|
||||
[mask]
|
||||
|
@ -34,7 +34,7 @@
|
|||
[mask]
|
||||
name=castle-convex-nw
|
||||
image=mask-castle-nw.png
|
||||
shift=-36,-45
|
||||
shift=-36,-36
|
||||
[/mask]
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
|||
[mask]
|
||||
name=castle-concave-ne
|
||||
image=mask-castle-ne.png
|
||||
shift=-18,-45
|
||||
shift=-18,-36
|
||||
[/mask]
|
||||
|
||||
[mask]
|
||||
|
@ -73,6 +73,6 @@
|
|||
[mask]
|
||||
name=castle-concave-nw
|
||||
image=mask-castle-nw.png
|
||||
shift=-36,-45
|
||||
shift=-36,-36
|
||||
[/mask]
|
||||
|
||||
|
|
|
@ -562,6 +562,7 @@ action_updateshroud="Update Shroud Now"
|
|||
action_continue="Continue Move"
|
||||
action_search="Find Label or Unit"
|
||||
action_help="Help"
|
||||
action_chatlog="View Chat Log"
|
||||
action_editnewmap="New Map"
|
||||
action_editloadmap="Load Map"
|
||||
action_editsavemap="Save Map"
|
||||
|
@ -587,6 +588,7 @@ hotkey_already_used="This HotKey is already in use."
|
|||
profile="Profile"
|
||||
|
||||
speak_allies_only="Send to allies only"
|
||||
chat_log="Chat Log"
|
||||
|
||||
speed="Speed:"
|
||||
speed_normal="Normal"
|
||||
|
@ -733,8 +735,11 @@ red="Red"
|
|||
blue="Blue"
|
||||
green="Green"
|
||||
yellow="Yellow"
|
||||
pink="Pink"
|
||||
purple="Purple"
|
||||
orange="Orange"
|
||||
grey="Grey"
|
||||
white="White"
|
||||
brown="Brown"
|
||||
|
||||
#terrain
|
||||
terrain="Terrain"
|
||||
|
|
|
@ -14,7 +14,7 @@ alignment=neutral
|
|||
advanceto=null
|
||||
cost=80
|
||||
ability=ambush
|
||||
usage=scout
|
||||
usage=mixed fighter
|
||||
unit_description="Elvish Avengers are extremely skillful and extremely quick, powerful in all forms of combat. Avengers are considered the best of all woodsmen in Wesnoth, and can ambush their foes in the forest, because they cannot be seen in the woods until just after they have attacked."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -15,7 +15,7 @@ level=2
|
|||
alignment=neutral
|
||||
advanceto=Elvish Marshal
|
||||
cost=40
|
||||
usage=mixed fighter
|
||||
usage=fighter
|
||||
unit_description="Skilled in commanding soldiers, Elvish Captains provide a bonus to all level-1 units on adjacent hexes. Captains are also skilled in both short- and long-range fighting."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -13,7 +13,7 @@ level=3
|
|||
alignment=neutral
|
||||
advanceto=null
|
||||
cost=100
|
||||
usage=mixed fighter
|
||||
usage=fighter
|
||||
unit_description="Elvish Champions are awesome masters of swordsmanship, inflicting large amounts of damage in close combat. Master fighters, they are also adept with the bow, able to inflict damage on their enemies from both near and far."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -13,7 +13,7 @@ level=2
|
|||
alignment=neutral
|
||||
advanceto=Elvish Champion
|
||||
cost=40
|
||||
usage=mixed fighter
|
||||
usage=fighter
|
||||
unit_description="Elvish Heroes focus on individual performance on the battlefield, having tweaked their combat skills to the very maximum. Elvish Heroes prefer fighting at close range with the sword, but are also skilled at the bow."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -12,7 +12,7 @@ level=2
|
|||
alignment=neutral
|
||||
advanceto=Elvish Sharpshooter
|
||||
cost=60
|
||||
usage=scout
|
||||
usage=archer
|
||||
unit_description="Elvish Marksman are expert in use of the bow. Their skill guarantees them a 60% chance to hit enemies, even those hidden in difficult terrain. This great skill with the bow compensates for their lack of skill in melee combat and lesser speed."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -16,7 +16,7 @@ level=3
|
|||
alignment=neutral
|
||||
advanceto=null
|
||||
cost=80
|
||||
usage=mixed fighter
|
||||
usage=fighter
|
||||
unit_description="Possessing one of the highest ranks in the Elven military, Elvish Marshals can lead any level 1 or 2 units in adjacent hexes, causing them to fight with increased skill. Marshals are also themselves greatly skilled in fighting, with both the sword and the bow."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -11,7 +11,7 @@ level=2
|
|||
alignment=neutral
|
||||
advanceto=Elvish Avenger
|
||||
cost=40
|
||||
usage=scout
|
||||
usage=mixed fighter
|
||||
ability=ambush
|
||||
unit_description="Elvish Rangers are quick and powerful. Skilled in both short- and long-range combat, Rangers are truly all-round fighters. The best of all woodsmen, Rangers cannot be seen by enemies while they are in forest, unless they have just made an attack, or there are enemies adjacent to them."
|
||||
get_hit_sound=groan.wav
|
||||
|
|
|
@ -11,7 +11,7 @@ level=3
|
|||
alignment=neutral
|
||||
advanceto=null
|
||||
cost=90
|
||||
usage=scout
|
||||
usage=archer
|
||||
unit_description="The most elite archers in all of Wesnoth, Elvish Sharpshooters are incredibly accurate, guaranteed a 60% chance to hit when attacking, even when firing very quickly. Sharpshooters are excellent at picking off entrenched enemies."
|
||||
get_hit_sound=groan.wav
|
||||
[attack]
|
||||
|
|
|
@ -300,6 +300,10 @@ wesnoth_editor_SOURCES = editor/editor.cpp \
|
|||
widgets/widget.hpp
|
||||
|
||||
AM_CXXFLAGS = @SDL_CFLAGS@ -DWESNOTH_PATH=\"$(pkgdatadir)\" -DLOCALEDIR=\"$(localedir)\"
|
||||
|
||||
if X11
|
||||
CXXFLAGS += -D_X11 @X_CFLAGS@
|
||||
endif
|
||||
if GCC
|
||||
CXXFLAGS += -fno-omit-frame-pointer
|
||||
endif
|
||||
|
|
|
@ -198,10 +198,11 @@ std::vector<std::string> get_text() {
|
|||
text.push_back("- wint3r");
|
||||
text.push_back("+ ");
|
||||
|
||||
text.push_back("+Past Contributors");
|
||||
text.push_back("+Contributors");
|
||||
text.push_back("- edge");
|
||||
text.push_back("- Frédéric Wagner");
|
||||
text.push_back("- Jan Zvánovec (jaz)");
|
||||
text.push_back("- Maksim Orlovich (SadEagle)");
|
||||
text.push_back("+ ");
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -1443,6 +1443,7 @@ bool clear_shroud_unit(const gamemap& map,
|
|||
|
||||
for(std::vector<gamemap::location>::const_iterator it =
|
||||
cleared_locations.begin(); it != cleared_locations.end(); ++it) {
|
||||
|
||||
if(units.count(*it)) {
|
||||
if(seen_units == NULL || known_units == NULL) {
|
||||
static const std::string sighted("sighted");
|
||||
|
@ -1757,6 +1758,10 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
disp->recalculate_minimap();
|
||||
}
|
||||
|
||||
for(std::set<gamemap::location>::const_iterator seen = seen_units.begin(); seen != seen_units.end(); ++seen) {
|
||||
game_events::fire("sighted",*seen,steps.back());
|
||||
}
|
||||
|
||||
assert(steps.size() <= route.size());
|
||||
|
||||
return steps.size();
|
||||
|
|
|
@ -1,16 +1,345 @@
|
|||
#include "clipboard.hpp"
|
||||
|
||||
#ifdef _X11
|
||||
|
||||
#define CLIPBOARD_FUNCS_DEFINED
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
/**
|
||||
The following are two classes which wrap the SDL's interface to X, including
|
||||
locking/unlocking, and which manage the atom internment. They exist mainly to make
|
||||
the actual clipboard code somewhat readable
|
||||
*/
|
||||
class XHelper
|
||||
{
|
||||
private:
|
||||
XHelper()
|
||||
{
|
||||
acquireCount_ = 0;
|
||||
acquire();
|
||||
|
||||
//Intern some atoms;
|
||||
const char* atoms[] = {
|
||||
"CLIPBOARD",
|
||||
"TEXT",
|
||||
"COMPOUND_TEXT",
|
||||
"UTF8_STRING",
|
||||
"WESNOTH_PASTE",
|
||||
"TARGETS"
|
||||
};
|
||||
|
||||
XInternAtoms(dpy(), (char**)atoms, 6, false, atomTable_);
|
||||
|
||||
release();
|
||||
}
|
||||
|
||||
static XHelper* s_instance_;
|
||||
|
||||
SDL_SysWMinfo wmInf_;
|
||||
|
||||
Atom atomTable_[6];
|
||||
int acquireCount_;
|
||||
public:
|
||||
static XHelper* instance()
|
||||
{
|
||||
if (!s_instance_)
|
||||
s_instance_ = new XHelper;
|
||||
return s_instance_;
|
||||
}
|
||||
|
||||
|
||||
Atom XA_CLIPBOARD()
|
||||
{
|
||||
return atomTable_[0];
|
||||
}
|
||||
|
||||
Atom XA_TEXT()
|
||||
{
|
||||
return atomTable_[1];
|
||||
}
|
||||
|
||||
Atom XA_COMPOUND_TEXT()
|
||||
{
|
||||
return atomTable_[2];
|
||||
}
|
||||
|
||||
Atom UTF8_STRING()
|
||||
{
|
||||
return atomTable_[3];
|
||||
}
|
||||
|
||||
Atom WES_PASTE()
|
||||
{
|
||||
return atomTable_[4];
|
||||
}
|
||||
|
||||
Atom XA_TARGETS()
|
||||
{
|
||||
return atomTable_[5];
|
||||
}
|
||||
|
||||
Display* dpy()
|
||||
{
|
||||
return wmInf_.info.x11.display;
|
||||
}
|
||||
|
||||
Window window()
|
||||
{
|
||||
return wmInf_.info.x11.window;
|
||||
}
|
||||
|
||||
void acquire(void)
|
||||
{
|
||||
++acquireCount_;
|
||||
if (acquireCount_ == 1) {
|
||||
SDL_VERSION (&wmInf_.version);
|
||||
SDL_GetWMInfo(&wmInf_);
|
||||
|
||||
wmInf_.info.x11.lock_func();
|
||||
}
|
||||
}
|
||||
|
||||
void release(void)
|
||||
{
|
||||
--acquireCount_;
|
||||
if (acquireCount_ == 0)
|
||||
wmInf_.info.x11.unlock_func();
|
||||
}
|
||||
};
|
||||
|
||||
XHelper* XHelper::s_instance_ = 0;
|
||||
|
||||
class UseX
|
||||
{
|
||||
public:
|
||||
UseX()
|
||||
{
|
||||
XHelper::instance()->acquire();
|
||||
}
|
||||
|
||||
~UseX()
|
||||
{
|
||||
XHelper::instance()->release();
|
||||
}
|
||||
|
||||
XHelper* operator->()
|
||||
{
|
||||
return XHelper::instance();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Note: unfortunately, SDL does not keep track of event timestamps.
|
||||
This means we are forced to use CurrentTime in many spots and are
|
||||
unable to perform many safety checks. Hence, the code below is
|
||||
not compliant to the ICCCM, and may ocassionally suffer from
|
||||
race conditions if an X client is connected to the server over
|
||||
a slow/high-latency link. This implementation is also very minimal.
|
||||
The text is assumed to be reasonably small as INCR transactions are not
|
||||
supported. MULTIPLE is not supported either.
|
||||
|
||||
We provide UTF8_STRING, COMPOUND_TEXT, and TEXT, and
|
||||
try to grab all of them, plus STRING (which is latin1).
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
We primarily. keep a copy of the string to response to data requests,
|
||||
but it also has an another function: in case we're both the source
|
||||
and destination, we just copy it accross; this is so that we
|
||||
don't have to handle SelectionRequest events while waiting for SelectionNotify.
|
||||
To make this work, however, this gets cleared when we loose CLIPBOARD
|
||||
*/
|
||||
static std::string clipboard_string;
|
||||
|
||||
|
||||
void handle_system_event(const SDL_Event& event)
|
||||
{
|
||||
XEvent& xev = event.syswm.msg->event.xevent;
|
||||
if (xev.type == SelectionRequest) {
|
||||
UseX x11;
|
||||
|
||||
//Since wesnoth does not notify us of selections,
|
||||
//we set both selection + clipboard when copying.
|
||||
if ((xev.xselectionrequest.owner == x11->window()) &&
|
||||
((xev.xselectionrequest.selection == XA_PRIMARY) ||
|
||||
(xev.xselectionrequest.selection == x11->XA_CLIPBOARD()))) {
|
||||
XEvent responseEvent;
|
||||
responseEvent.xselection.type = SelectionNotify;
|
||||
responseEvent.xselection.display = x11->dpy();
|
||||
responseEvent.xselection.requestor = xev.xselectionrequest.requestor;
|
||||
responseEvent.xselection.selection = xev.xselectionrequest.selection;
|
||||
responseEvent.xselection.target = xev.xselectionrequest.target;
|
||||
responseEvent.xselection.property = None; //nothing available, by default
|
||||
responseEvent.xselection.time = xev.xselectionrequest.time;
|
||||
|
||||
//std::cout<<"Request for target:"<<XGetAtomName(x11->dpy(), xev.xselectionrequest.target)<<"\n";
|
||||
|
||||
//### presently don't handle XA_STRING as it must be latin1
|
||||
|
||||
if (xev.xselectionrequest.target == x11->XA_TARGETS()) {
|
||||
responseEvent.xselection.property = xev.xselectionrequest.property;
|
||||
|
||||
Atom supported[] = {
|
||||
x11->XA_TEXT(),
|
||||
x11->XA_COMPOUND_TEXT(),
|
||||
x11->UTF8_STRING(),
|
||||
x11->XA_TARGETS()
|
||||
};
|
||||
|
||||
XChangeProperty(x11->dpy(), responseEvent.xselection.requestor,
|
||||
xev.xselectionrequest.property, XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char*)supported, 4);
|
||||
}
|
||||
|
||||
//The encoding of XA_TEXT and XA_COMPOUND_TEXT is not specified
|
||||
//by the ICCCM... So we assume wesnoth native/utf-8 for simplicity.
|
||||
//modern apps are going to use UTF8_STRING anyway
|
||||
if (xev.xselectionrequest.target == x11->XA_TEXT() ||
|
||||
xev.xselectionrequest.target == x11->XA_COMPOUND_TEXT() ||
|
||||
xev.xselectionrequest.target == x11->UTF8_STRING()) {
|
||||
responseEvent.xselection.property = xev.xselectionrequest.property;
|
||||
|
||||
XChangeProperty(x11->dpy(), responseEvent.xselection.requestor,
|
||||
xev.xselectionrequest.property,
|
||||
xev.xselectionrequest.target, 8, PropModeReplace,
|
||||
(const unsigned char*) clipboard_string.c_str(), clipboard_string.length());
|
||||
}
|
||||
|
||||
XSendEvent(x11->dpy(), xev.xselectionrequest.requestor, False, NoEventMask,
|
||||
&responseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (xev.type == SelectionClear) {
|
||||
UseX x11;
|
||||
|
||||
if (xev.xselectionclear.selection == x11->XA_CLIPBOARD())
|
||||
clipboard_string = ""; //We no longer own the clipboard, don't try in-process C&P
|
||||
}
|
||||
}
|
||||
|
||||
void copy_to_clipboard(const std::string& text)
|
||||
{
|
||||
if (text.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clipboard_string = text;
|
||||
|
||||
UseX x11;
|
||||
|
||||
XSetSelectionOwner(x11->dpy(), XA_PRIMARY, x11->window(), CurrentTime);
|
||||
XSetSelectionOwner(x11->dpy(), x11->XA_CLIPBOARD(), x11->window(), CurrentTime);
|
||||
}
|
||||
|
||||
|
||||
//Tries to grab a given target. Returns true if successful, false otherwise
|
||||
static bool try_grab_target(Atom target, std::string& ret)
|
||||
{
|
||||
UseX x11;
|
||||
|
||||
//Cleanup previous data
|
||||
XDeleteProperty(x11->dpy(), x11->window(), x11->WES_PASTE());
|
||||
XSync (x11->dpy(), False);
|
||||
|
||||
//std::cout<<"We request target:"<<XGetAtomName(x11->dpy(), target)<<"\n";
|
||||
|
||||
//Request information
|
||||
XConvertSelection(x11->dpy(), x11->XA_CLIPBOARD(), target,
|
||||
x11->WES_PASTE(), x11->window(), CurrentTime);
|
||||
|
||||
//Wait (with timeout) for a response SelectionNotify
|
||||
for (int attempt = 0; attempt < 15; attempt++) {
|
||||
if (XPending(x11->dpy())) {
|
||||
XEvent selectNotify;
|
||||
while (XCheckTypedWindowEvent(x11->dpy(), x11->window(), SelectionNotify, &selectNotify)) {
|
||||
if (selectNotify.xselection.property == None)
|
||||
//Not supported. Say so.
|
||||
return false;
|
||||
else if (selectNotify.xselection.property == x11->WES_PASTE() &&
|
||||
selectNotify.xselection.target == target) {
|
||||
//The size
|
||||
unsigned long length = 0;
|
||||
unsigned char* data;
|
||||
|
||||
//these 3 XGetWindowProperty returns but we don't use
|
||||
Atom typeRet;
|
||||
int formatRet;
|
||||
unsigned long remaining;
|
||||
|
||||
// std::cout<<"Grab:"<<XGetAtomName(x11->dpy(), target)<<"\n";
|
||||
|
||||
//Grab the text out of the property
|
||||
XGetWindowProperty(x11->dpy(), x11->window(),
|
||||
selectNotify.xselection.property,
|
||||
0, 65535/4, True, target,
|
||||
&typeRet, &formatRet, &length, &remaining, &data);
|
||||
|
||||
if (data && length) {
|
||||
ret = (char*)data;
|
||||
XFree(data);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
//Timed out -- return empty string
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string copy_from_clipboard()
|
||||
{
|
||||
if (!clipboard_string.empty())
|
||||
return clipboard_string; //in-wesnoth copy-paste
|
||||
|
||||
std::string ret;
|
||||
|
||||
UseX x11;
|
||||
|
||||
if (try_grab_target(x11->UTF8_STRING(), ret))
|
||||
return ret;
|
||||
|
||||
if (try_grab_target(x11->XA_COMPOUND_TEXT(), ret))
|
||||
return ret;
|
||||
|
||||
if (try_grab_target(x11->XA_TEXT(), ret))
|
||||
return ret;
|
||||
|
||||
if (try_grab_target(XA_STRING, ret)) //acroread only provides this
|
||||
return ret;
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define CLIPBOARD_FUNCS_DEFINED
|
||||
|
||||
void handle_system_event(const SDL_Event& )
|
||||
{}
|
||||
|
||||
void copy_to_clipboard(const std::string& text)
|
||||
{
|
||||
if(text.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
if(!OpenClipboard(0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -24,12 +353,10 @@ void copy_to_clipboard(const std::string& text)
|
|||
GlobalUnlock(clip_buffer);
|
||||
SetClipboardData(CF_TEXT,clip_buffer);
|
||||
CloseClipboard();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string copy_from_clipboard()
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(OpenClipboard(NULL)) {
|
||||
const HANDLE data = GetClipboardData(CF_TEXT);
|
||||
char* const buffer = reinterpret_cast<char*>(GlobalLock(data));
|
||||
|
@ -38,7 +365,21 @@ std::string copy_from_clipboard()
|
|||
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CLIPBOARD_FUNCS_DEFINED
|
||||
|
||||
void copy_to_clipboard(const std::string& text)
|
||||
{
|
||||
}
|
||||
|
||||
std::string copy_from_clipboard()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,8 +2,13 @@
|
|||
#define CLIPBOARD_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include "SDL.h"
|
||||
|
||||
void copy_to_clipboard(const std::string& text);
|
||||
std::string copy_from_clipboard();
|
||||
|
||||
#endif
|
||||
#ifdef _X11
|
||||
void handle_system_event(const SDL_Event& ev);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,25 +45,37 @@ void advance_unit(const game_data& info,
|
|||
if(u == units.end() || u->second.advances() == false)
|
||||
return;
|
||||
|
||||
std::cerr << "advance_unit: " << u->second.type().name() << "\n";
|
||||
|
||||
const std::vector<std::string>& options = u->second.type().advances_to();
|
||||
|
||||
std::vector<std::string> lang_options;
|
||||
|
||||
std::vector<unit> sample_units;
|
||||
for(std::vector<std::string>::const_iterator op = options.begin();
|
||||
op != options.end(); ++op) {
|
||||
for(std::vector<std::string>::const_iterator op = options.begin(); op != options.end(); ++op) {
|
||||
sample_units.push_back(::get_advanced_unit(info,units,loc,*op));
|
||||
const unit_type& type = sample_units.back().type();
|
||||
lang_options.push_back("&" + type.image() + "," + type.language_name());
|
||||
}
|
||||
|
||||
const config::child_list& mod_options = u->second.get_modification_advances();
|
||||
|
||||
for(config::child_list::const_iterator mod = mod_options.begin(); mod != mod_options.end(); ++mod) {
|
||||
sample_units.push_back(::get_advanced_unit(info,units,loc,u->second.type().name()));
|
||||
sample_units.back().add_modification("advance",**mod);
|
||||
const unit_type& type = sample_units.back().type();
|
||||
lang_options.push_back("&" + type.image() + "," + translate_string_default("advance_" + (**mod)["id"],(**mod)["description"]));
|
||||
}
|
||||
|
||||
std::cerr << "options: " << options.size() << "\n";
|
||||
|
||||
int res = 0;
|
||||
|
||||
if(options.empty()) {
|
||||
if(lang_options.empty()) {
|
||||
return;
|
||||
} else if(random_choice) {
|
||||
res = rand()%options.size();
|
||||
} else if(options.size() > 1) {
|
||||
res = rand()%lang_options.size();
|
||||
} else if(lang_options.size() > 1) {
|
||||
|
||||
const events::event_context dialog_events_context;
|
||||
unit_preview_pane unit_preview(gui,&map,sample_units);
|
||||
|
@ -77,6 +89,7 @@ void advance_unit(const game_data& info,
|
|||
|
||||
recorder.choose_option(res);
|
||||
|
||||
std::cerr << "animating advancement...\n";
|
||||
animate_unit_advancement(info,units,loc,gui,size_t(res));
|
||||
}
|
||||
|
||||
|
@ -90,7 +103,9 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
|
|||
}
|
||||
|
||||
const std::vector<std::string>& options = u->second.type().advances_to();
|
||||
if(choice >= options.size()) {
|
||||
const config::child_list& mod_options = u->second.get_modification_advances();
|
||||
|
||||
if(choice >= options.size() + mod_options.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -107,7 +122,13 @@ bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::lo
|
|||
}
|
||||
}
|
||||
|
||||
::advance_unit(info,units,loc,options[choice]);
|
||||
const std::string& chosen_unit = choice < options.size() ? options[choice] : u->second.type().name();
|
||||
::advance_unit(info,units,loc,chosen_unit);
|
||||
|
||||
u = units.find(loc);
|
||||
if(u != units.end() && choice >= options.size()) {
|
||||
u->second.add_modification("advance",*mod_options[choice - options.size()]);
|
||||
}
|
||||
|
||||
gui.invalidate_unit();
|
||||
|
||||
|
@ -594,7 +615,7 @@ namespace {
|
|||
}
|
||||
|
||||
unit_preview_pane::unit_preview_pane(display& disp, const gamemap* map, const unit& u, TYPE type, bool on_left_side)
|
||||
: gui::preview_pane(disp), details_button_(disp,translate_string("profile"),gui::button::TYPE_PRESS,"lite",gui::button::MINIMUM_SPACE),
|
||||
: gui::preview_pane(disp), details_button_(disp,translate_string("profile"),gui::button::TYPE_PRESS,"lite_small",gui::button::MINIMUM_SPACE),
|
||||
map_(map), units_(&unit_store_), index_(0), left_(on_left_side),
|
||||
weapons_(type == SHOW_ALL)
|
||||
{
|
||||
|
@ -603,7 +624,7 @@ unit_preview_pane::unit_preview_pane(display& disp, const gamemap* map, const un
|
|||
}
|
||||
|
||||
unit_preview_pane::unit_preview_pane(display& disp, const gamemap* map, const std::vector<unit>& units, TYPE type, bool on_left_side)
|
||||
: gui::preview_pane(disp), details_button_(disp,translate_string("profile"),gui::button::TYPE_PRESS,"lite",gui::button::MINIMUM_SPACE),
|
||||
: gui::preview_pane(disp), details_button_(disp,translate_string("profile"),gui::button::TYPE_PRESS,"lite_small",gui::button::MINIMUM_SPACE),
|
||||
map_(map), units_(&units), index_(0), left_(on_left_side),
|
||||
weapons_(type == SHOW_ALL)
|
||||
{
|
||||
|
@ -714,7 +735,7 @@ void unit_preview_pane::draw()
|
|||
details << string_table["hp"] << ": " << u.hitpoints()
|
||||
<< "/" << u.max_hitpoints() << "\n";
|
||||
|
||||
if(u.type().advances_to().empty()) {
|
||||
if(u.can_advance() == false) {
|
||||
details << string_table["xp"] << ": " << u.experience() << "/-";
|
||||
} else {
|
||||
//if killing a unit the same level as us would level us up,
|
||||
|
|
|
@ -841,7 +841,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
|||
details << string_table["hp"] << ": " << u.hitpoints()
|
||||
<< "/" << u.max_hitpoints() << "\n";
|
||||
|
||||
if(u.type().advances_to().empty()) {
|
||||
if(u.can_advance() == false) {
|
||||
details << string_table["xp"] << ": " << u.experience() << "/-";
|
||||
} else {
|
||||
//if killing a unit the same level as us would level us up,
|
||||
|
@ -1219,10 +1219,10 @@ void display::draw_unit_on_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
draw_bar(*energy_file,xpos,ypos,(u.max_hitpoints()*2)/3,unit_energy,energy_colour,bar_alpha);
|
||||
}
|
||||
|
||||
if(u.experience() > 0 && u.type().can_advance()) {
|
||||
if(u.experience() > 0 && u.can_advance()) {
|
||||
const double filled = double(u.experience())/double(u.max_experience());
|
||||
const int level = maximum<int>(u.type().level(),1);
|
||||
const SDL_Color normal_colour = {173,200,248,0}, near_advance_colour = {255,255,255,0};
|
||||
const SDL_Color normal_colour = {02,153,255,0}, near_advance_colour = {255,255,255,0};
|
||||
const bool near_advance = u.max_experience() - u.experience() <= game_config::kill_experience*level;
|
||||
const SDL_Color colour = near_advance ? near_advance_colour : normal_colour;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "clipboard.hpp"
|
||||
#include "cursor.hpp"
|
||||
#include "events.hpp"
|
||||
#include "mouse.hpp"
|
||||
|
@ -279,6 +280,14 @@ void pump()
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _X11
|
||||
case SDL_SYSWMEVENT: {
|
||||
//clipboard support for X11
|
||||
handle_system_event(event);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SDL_QUIT: {
|
||||
throw CVideo::quit();
|
||||
|
|
|
@ -116,7 +116,7 @@ struct font_style_setter
|
|||
//SDL_ttf to segfault. We work around this here by disallowing combinations
|
||||
//of styles
|
||||
if((style&TTF_STYLE_UNDERLINE) != 0) {
|
||||
style = TTF_STYLE_UNDERLINE;
|
||||
style = TTF_STYLE_NORMAL; //TTF_STYLE_UNDERLINE;
|
||||
} else if((style&TTF_STYLE_BOLD) != 0) {
|
||||
style = TTF_STYLE_BOLD;
|
||||
} else if((style&TTF_STYLE_ITALIC) != 0) {
|
||||
|
@ -368,7 +368,7 @@ SDL_Rect draw_text_line(SDL_Surface *gui_surface, const SDL_Rect& area, int size
|
|||
SDL_Rect src = dest;
|
||||
src.x = 0;
|
||||
src.y = 0;
|
||||
sdl_safe_blit(surface,&src,gui_surface,&dest);
|
||||
SDL_BlitSurface(surface,&src,gui_surface,&dest);
|
||||
}
|
||||
|
||||
if(use_tooltips) {
|
||||
|
|
|
@ -472,6 +472,9 @@ int play_game(int argc, char** argv)
|
|||
}
|
||||
|
||||
const cursor::manager cursor_manager;
|
||||
#ifdef _X11
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
||||
#endif
|
||||
|
||||
std::cerr << "initialized gui\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
|
|
@ -739,7 +739,12 @@ bool event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
gamemap::location loc;
|
||||
bool remove_overlay = false;
|
||||
if(filter != NULL) {
|
||||
loc = gamemap::location(*filter);
|
||||
for(unit_map::const_iterator u = units->begin(); u != units->end(); ++u) {
|
||||
if(game_events::unit_matches_filter(u,*filter)) {
|
||||
loc = u->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(loc.valid() == false) {
|
||||
|
@ -749,10 +754,7 @@ bool event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
|
||||
const unit_map::iterator u = units->find(loc);
|
||||
|
||||
if(u == units->end())
|
||||
return rval;
|
||||
|
||||
if(filter == NULL || u->second.matches_filter(*filter)) {
|
||||
if(u != units->end() && (filter == NULL || u->second.matches_filter(*filter))) {
|
||||
const std::string& lang = string_table[id];
|
||||
if(!lang.empty())
|
||||
text = lang;
|
||||
|
|
|
@ -512,6 +512,7 @@ void extract_summary_data_from_save(const game_state& state, config& out)
|
|||
}
|
||||
|
||||
out["leader"] = leader;
|
||||
out["map_data"] = "";
|
||||
|
||||
if(!shrouded) {
|
||||
if(has_snapshot) {
|
||||
|
|
195
src/help.cpp
195
src/help.cpp
|
@ -34,9 +34,13 @@
|
|||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
const config *help_config = NULL;
|
||||
const config *game_config = NULL;
|
||||
game_data *game_info = NULL;
|
||||
// The default toplevel.
|
||||
help::section toplevel;
|
||||
// All sections and topics not referenced from the default toplevel.
|
||||
help::section hidden_sections;
|
||||
|
||||
config dummy_cfg;
|
||||
std::vector<std::string> empty_string_vector;
|
||||
const int max_section_level = 15;
|
||||
|
@ -67,6 +71,9 @@ namespace {
|
|||
if (id.find("weaponspecial_") == 0) {
|
||||
return false;
|
||||
}
|
||||
if (id == "hidden") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -131,15 +138,118 @@ namespace help {
|
|||
|
||||
help_manager::help_manager(const config *cfg, game_data *gameinfo) {
|
||||
game_config = cfg == NULL ? &dummy_cfg : cfg;
|
||||
game_info = gameinfo;
|
||||
if (game_config != NULL) {
|
||||
help_config = game_config->child("help");
|
||||
const config *help_config = game_config->child("help");
|
||||
if (help_config == NULL) {
|
||||
help_config = &dummy_cfg;
|
||||
}
|
||||
try {
|
||||
toplevel = parse_config(help_config);
|
||||
// Create a config object that contains everything that is
|
||||
// not referenced from the toplevel element. Read this
|
||||
// config and save these sections and topics so that they
|
||||
// can be referenced later on when showing help about
|
||||
// specified things, but that should not be shown when
|
||||
// opening the help browser in the default manner.
|
||||
config hidden_toplevel;
|
||||
std::stringstream ss;
|
||||
config::const_child_itors itors;
|
||||
for (itors = help_config->child_range("section"); itors.first != itors.second;
|
||||
itors.first++) {
|
||||
const std::string id = (*(*itors.first))["id"];
|
||||
if (find_section(toplevel, id) == NULL) {
|
||||
// This section does not exist referenced from the
|
||||
// toplevel. Hence, add it to the hidden ones if it
|
||||
// is not referenced from another section.
|
||||
if (!section_is_referenced(id, *help_config)) {
|
||||
if (ss.str() != "") {
|
||||
ss << ",";
|
||||
}
|
||||
ss << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
hidden_toplevel["sections"] = ss.str();
|
||||
ss.str("");
|
||||
for (itors = help_config->child_range("topic"); itors.first != itors.second;
|
||||
itors.first++) {
|
||||
const std::string id = (*(*itors.first))["id"];
|
||||
if (find_topic(toplevel, id) == NULL) {
|
||||
if (!topic_is_referenced(id, *help_config)) {
|
||||
if (ss.str() != "") {
|
||||
ss << ",";
|
||||
}
|
||||
ss << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
hidden_toplevel["topics"] = ss.str();
|
||||
config hidden_cfg = *help_config;
|
||||
// Change the toplevel to our new, custom built one.
|
||||
hidden_cfg.clear_children("toplevel");
|
||||
hidden_cfg.add_child("toplevel", hidden_toplevel);
|
||||
hidden_sections = parse_config(&hidden_cfg);
|
||||
}
|
||||
catch (parse_error e) {
|
||||
std::stringstream msg;
|
||||
msg << "Parse error when parsing help text: '" << e.message << "'";
|
||||
std::cerr << msg.str() << std::endl;
|
||||
}
|
||||
}
|
||||
game_info = gameinfo;
|
||||
}
|
||||
|
||||
help_manager::~help_manager() {
|
||||
game_config = NULL;
|
||||
game_info = NULL;
|
||||
toplevel = section();
|
||||
hidden_sections = section();
|
||||
}
|
||||
|
||||
bool section_is_referenced(const std::string §ion_id, const config &cfg) {
|
||||
const config *toplevel = cfg.child("toplevel");
|
||||
if (toplevel != NULL) {
|
||||
const std::vector<std::string> toplevel_refs
|
||||
= config::quoted_split((*toplevel)["sections"]);
|
||||
if (std::find(toplevel_refs.begin(), toplevel_refs.end(), section_id)
|
||||
!= toplevel_refs.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (config::const_child_itors itors = cfg.child_range("section");
|
||||
itors.first != itors.second; itors.first++) {
|
||||
const std::vector<std::string> sections_refd
|
||||
= config::quoted_split((*(*itors.first))["sections"]);
|
||||
if (std::find(sections_refd.begin(), sections_refd.end(), section_id)
|
||||
!= sections_refd.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool topic_is_referenced(const std::string &topic_id, const config &cfg) {
|
||||
const config *toplevel = cfg.child("toplevel");
|
||||
if (toplevel != NULL) {
|
||||
const std::vector<std::string> toplevel_refs
|
||||
= config::quoted_split((*toplevel)["topics"]);
|
||||
if (std::find(toplevel_refs.begin(), toplevel_refs.end(), topic_id)
|
||||
!= toplevel_refs.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (config::const_child_itors itors = cfg.child_range("section");
|
||||
itors.first != itors.second; itors.first++) {
|
||||
const std::vector<std::string> topics_refd
|
||||
= config::quoted_split((*(*itors.first))["topics"]);
|
||||
if (std::find(topics_refd.begin(), topics_refd.end(), topic_id)
|
||||
!= topics_refd.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
||||
section &sec, int level) {
|
||||
if (level > max_section_level) {
|
||||
|
@ -179,7 +289,7 @@ void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
|||
generate_sections((*section_cfg)["generator"]);
|
||||
std::transform(generated_sections.begin(), generated_sections.end(),
|
||||
std::back_inserter(sec.sections), create_section());
|
||||
const std::vector<std::string> topics = config::quoted_split((*section_cfg)["topics"]);
|
||||
const std::vector<std::string> topics = config::quoted_split((*section_cfg)["topics"]);
|
||||
// Find all topics in this section.
|
||||
for (it = topics.begin(); it != topics.end(); it++) {
|
||||
config const *topic_cfg = help_cfg->find_child("topic", "id", *it);
|
||||
|
@ -205,7 +315,6 @@ void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
|||
generate_topics((*section_cfg)["generator"]);
|
||||
std::copy(generated_topics.begin(), generated_topics.end(),
|
||||
std::back_inserter(sec.topics));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,10 +659,6 @@ std::string generate_about_text() {
|
|||
return text;
|
||||
}
|
||||
|
||||
help_manager::~help_manager() {
|
||||
help_config = NULL;
|
||||
}
|
||||
|
||||
bool topic::operator==(const topic &t) const {
|
||||
return t.id == id;
|
||||
}
|
||||
|
@ -581,6 +686,9 @@ section::section(const section &sec)
|
|||
}
|
||||
|
||||
section& section::operator=(const section &sec) {
|
||||
title = sec.title;
|
||||
id = sec.id;
|
||||
std::copy(sec.topics.begin(), sec.topics.end(), std::back_inserter(topics));
|
||||
std::transform(sec.sections.begin(), sec.sections.end(),
|
||||
std::back_inserter(sections), create_section());
|
||||
return *this;
|
||||
|
@ -955,10 +1063,20 @@ void help_text_area::set_items(const std::vector<std::string> &parsed_items,
|
|||
void help_text_area::handle_ref_cfg(const config &cfg) {
|
||||
const std::string dst = cfg["dst"];
|
||||
const std::string text = cfg["text"];
|
||||
const bool force = get_bool(cfg["force"]);
|
||||
bool show_ref = true;
|
||||
if (find_topic(toplevel_, dst) == NULL && !force) {
|
||||
show_ref = false;
|
||||
}
|
||||
if (dst == "" || text == "") {
|
||||
throw parse_error("Ref markup must have both dst and text attributes.");
|
||||
}
|
||||
add_text_item(text, dst);
|
||||
if (show_ref) {
|
||||
add_text_item(text, dst);
|
||||
}
|
||||
else {
|
||||
add_text_item(text);
|
||||
}
|
||||
}
|
||||
|
||||
void help_text_area::handle_img_cfg(const config &cfg) {
|
||||
|
@ -1329,7 +1447,7 @@ void help_text_area::draw() {
|
|||
if (dst.y < (int)height() && dst.y + (*it).surf->h > 0) {
|
||||
dst.x += location().x;
|
||||
dst.y += location().y;
|
||||
sdl_safe_blit((*it).surf, NULL, screen, &dst);
|
||||
SDL_BlitSurface((*it).surf, NULL, screen, &dst);
|
||||
}
|
||||
}
|
||||
update_rect(location());
|
||||
|
@ -1431,7 +1549,7 @@ std::string help_text_area::ref_at(const int x, const int y) {
|
|||
|
||||
|
||||
|
||||
help_browser::help_browser(display &disp, section &toplevel)
|
||||
help_browser::help_browser(display &disp, const section &toplevel)
|
||||
: gui::widget(disp), disp_(disp), menu_(disp, toplevel),
|
||||
text_area_(disp, toplevel), toplevel_(toplevel), ref_cursor_(false),
|
||||
back_button_(disp, translate_string("help_back"), gui::button::TYPE_PRESS),
|
||||
|
@ -1616,6 +1734,21 @@ const topic *find_topic(const section &sec, const std::string &id) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const section *find_section(const section &sec, const std::string &id) {
|
||||
section_list::const_iterator sit =
|
||||
std::find_if(sec.sections.begin(), sec.sections.end(), has_id(id));
|
||||
if (sit != sec.sections.end()) {
|
||||
return *sit;
|
||||
}
|
||||
for (sit = sec.sections.begin(); sit != sec.sections.end(); sit++) {
|
||||
const section *s = find_section(*(*sit), id);
|
||||
if (s != NULL) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void help_browser::show_topic(const std::string &topic_id) {
|
||||
const topic *t = find_topic(toplevel_, topic_id);
|
||||
if (t != NULL) {
|
||||
|
@ -1833,6 +1966,41 @@ std::string get_first_word(const std::string &s) {
|
|||
}
|
||||
|
||||
void show_help(display &disp, std::string show_topic, int xloc, int yloc) {
|
||||
show_help(disp, toplevel, show_topic, xloc, yloc);
|
||||
}
|
||||
|
||||
void show_help(display &disp, const std::vector<std::string> &topics_to_show,
|
||||
const std::vector<std::string> §ions_to_show, const std::string show_topic,
|
||||
int xloc, int yloc) {
|
||||
section to_show;
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = topics_to_show.begin(); it != topics_to_show.end(); it++) {
|
||||
// Check both the visible toplevel and the hidden sections.
|
||||
const topic *t = find_topic(toplevel, *it);
|
||||
t = t == NULL ? find_topic(hidden_sections, *it) : t;
|
||||
if (t != NULL) {
|
||||
to_show.topics.push_back(*t);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Warning: topic with id " << *it << " does not exist." << std::endl;
|
||||
}
|
||||
}
|
||||
for (it = sections_to_show.begin(); it != sections_to_show.end(); it++) {
|
||||
const section *s = find_section(toplevel, *it);
|
||||
s = s == NULL ? find_section(hidden_sections, *it) : s;
|
||||
if (s != NULL) {
|
||||
to_show.add_section(*s);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Warning: section with id " << *it << " does not exist." << std::endl;
|
||||
}
|
||||
}
|
||||
show_help(disp, to_show, show_topic, xloc, yloc);
|
||||
}
|
||||
|
||||
/// Open a help dialog using a toplevel other than the default.
|
||||
void show_help(display &disp, const section &toplevel_sec, const std::string show_topic,
|
||||
int xloc, int yloc) {
|
||||
const events::event_context dialog_events_context;
|
||||
const gui::dialog_manager manager;
|
||||
const events::resize_lock prevent_resizing;
|
||||
|
@ -1861,8 +2029,7 @@ void show_help(display &disp, std::string show_topic, int xloc, int yloc) {
|
|||
NULL, &buttons_ptr, &restorer);
|
||||
|
||||
try {
|
||||
section toplevel = parse_config(help_config);
|
||||
help_browser hb(disp, toplevel);
|
||||
help_browser hb(disp, toplevel_sec);
|
||||
hb.set_location(xloc + left_padding, yloc + top_padding);
|
||||
hb.set_width(width - left_padding - right_padding);
|
||||
hb.set_height(height - top_padding - bot_padding);
|
||||
|
|
37
src/help.hpp
37
src/help.hpp
|
@ -83,6 +83,7 @@ public:
|
|||
has_id(const std::string &id) : id_(id) {}
|
||||
bool operator()(const topic &t) { return t.id == id_; }
|
||||
bool operator()(const section &s) { return s.id == id_; }
|
||||
bool operator()(const section *s) { return s != NULL && s->id == id_; }
|
||||
private:
|
||||
const std::string id_;
|
||||
};
|
||||
|
@ -345,7 +346,7 @@ private:
|
|||
/// A help browser widget.
|
||||
class help_browser : public gui::widget {
|
||||
public:
|
||||
help_browser(display &disp, section &toplevel);
|
||||
help_browser(display &disp, const section &toplevel);
|
||||
|
||||
// Overloaded from widget so that the layout may be adjusted to fit
|
||||
// the new dimensions.
|
||||
|
@ -403,8 +404,6 @@ UNIT_DESCRIPTION_TYPE description_type(const unit_type &type);
|
|||
std::vector<topic> generate_ability_topics();
|
||||
std::vector<topic> generate_weapon_special_topics();
|
||||
|
||||
|
||||
|
||||
/// Parse a help config, return the top level section. Return an empty
|
||||
/// section if cfg is NULL.
|
||||
section parse_config(const config *cfg);
|
||||
|
@ -412,11 +411,23 @@ section parse_config(const config *cfg);
|
|||
void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
||||
section &sec, int level=0);
|
||||
|
||||
/// Return true if the section with id section_id is referenced from
|
||||
/// another section in the config, or the toplevel.
|
||||
bool section_is_referenced(const std::string §ion_id, const config &cfg);
|
||||
/// Return true if the topic with id topic_id is referenced from
|
||||
/// another section in the config, or the toplevel.
|
||||
bool topic_is_referenced(const std::string &topic_id, const config &cfg);
|
||||
|
||||
/// Search for the topic with the specified identifier in the section
|
||||
/// and it's subsections. Return the found topic, or NULL if none could
|
||||
/// and its subsections. Return the found topic, or NULL if none could
|
||||
/// be found.
|
||||
const topic *find_topic(const section &sec, const std::string &id);
|
||||
|
||||
/// Search for the section with the specified identifier in the section
|
||||
/// and its subsections. Return the found section or NULL if none could
|
||||
/// be found.
|
||||
const section *find_section(const section &sec, const std::string &id);
|
||||
|
||||
/// Parse a text string. Return a vector with the different parts of the
|
||||
/// text. Each markup item is a separate part while the text between
|
||||
/// markups are separate parts.
|
||||
|
@ -450,8 +461,22 @@ std::string cap(const std::string &s);
|
|||
/// it.
|
||||
std::string get_first_word(const std::string &s);
|
||||
|
||||
/// Open a help dialog. The help topic will have the topic with id
|
||||
/// show_topic open if it is not the empty string.
|
||||
/// Open a help dialog showing the topics with ids topics_to_show and
|
||||
/// the sections with ids sections_to_show. Subsections and subtopics of
|
||||
/// the sections will be added recursively according to the help config.
|
||||
void show_help(display &disp, const std::vector<std::string> &topics_to_show,
|
||||
const std::vector<std::string> §ions_to_show, const std::string show_topic="",
|
||||
int xloc=-1, int yloc=-1);
|
||||
|
||||
/// Open a help dialog using a toplevel other than the default. This
|
||||
/// allows for complete customization of the contents, although not in a
|
||||
/// very easy way.
|
||||
void show_help(display &disp, const section &toplevel, const std::string show_topic="",
|
||||
int xloc=-1, int yloc=-1);
|
||||
|
||||
/// Open the help browser. The help browser will have the topic with id
|
||||
/// show_topic open if it is not the empty string. The default topic
|
||||
/// will be shown if show_topic sis the empty string.
|
||||
void show_help(display &disp, const std::string show_topic="", int xloc=-1, int yloc=-1);
|
||||
|
||||
} // End namespace help.
|
||||
|
|
|
@ -92,6 +92,7 @@ HOTKEY_COMMAND string_to_command(const std::string& str)
|
|||
m.insert(val("speaktoally",HOTKEY_SPEAK_ALLY));
|
||||
m.insert(val("speaktoall",HOTKEY_SPEAK_ALL));
|
||||
m.insert(val("help",HOTKEY_HELP));
|
||||
m.insert(val("chatlog",HOTKEY_CHAT_LOG));
|
||||
}
|
||||
|
||||
const std::map<std::string,HOTKEY_COMMAND>::const_iterator i = m.find(str);
|
||||
|
@ -490,6 +491,11 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
|
|||
executor->show_help();
|
||||
}
|
||||
break;
|
||||
case HOTKEY_CHAT_LOG:
|
||||
if(executor) {
|
||||
executor->show_chat_log();
|
||||
}
|
||||
break;
|
||||
case HOTKEY_EDIT_SET_TERRAIN:
|
||||
if(executor)
|
||||
executor->edit_set_terrain();
|
||||
|
|
|
@ -36,6 +36,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
|
|||
HOTKEY_LABEL_TERRAIN, HOTKEY_SHOW_ENEMY_MOVES, HOTKEY_BEST_ENEMY_MOVES,
|
||||
HOTKEY_DELAY_SHROUD, HOTKEY_UPDATE_SHROUD, HOTKEY_CONTINUE_MOVE,
|
||||
HOTKEY_SEARCH, HOTKEY_SPEAK_ALLY, HOTKEY_SPEAK_ALL, HOTKEY_HELP,
|
||||
HOTKEY_CHAT_LOG,
|
||||
|
||||
//editing specific commands
|
||||
HOTKEY_EDIT_SET_TERRAIN,
|
||||
|
@ -120,6 +121,7 @@ public:
|
|||
virtual void continue_move() {}
|
||||
virtual void search() {}
|
||||
virtual void show_help() {}
|
||||
virtual void show_chat_log() {}
|
||||
|
||||
// Map editor stuff.
|
||||
virtual void edit_set_terrain() {}
|
||||
|
|
|
@ -332,7 +332,7 @@ SDL_Surface* get_image(const image::locator& i_locator, TYPE type, COLOUR_ADJUST
|
|||
const scoped_sdl_surface scoped_surface(result);
|
||||
result = adjust_surface_colour(scaled_surf,red_adjust,green_adjust,blue_adjust);
|
||||
} else {
|
||||
result = clone_surface(scaled_surf);
|
||||
result = create_optimized_surface(scaled_surf);
|
||||
}
|
||||
|
||||
if(result == NULL) {
|
||||
|
@ -518,7 +518,7 @@ SDL_Surface* getMinimap(int w, int h, const gamemap& map,
|
|||
assert(surf != NULL);
|
||||
|
||||
SDL_Rect maprect = {x*scale*3/4,y*scale + (is_odd(x) ? scale/2 : 0),0,0};
|
||||
sdl_safe_blit(surf, NULL, minimap, &maprect);
|
||||
SDL_BlitSurface(surf, NULL, minimap, &maprect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -321,7 +321,7 @@ gamemap::TERRAIN gamemap::get_terrain(const gamemap::location& loc) const
|
|||
TERRAIN used_terrain = 0;
|
||||
int terrain_count = 0;
|
||||
for(int i = 0; i != nitems; ++i) {
|
||||
if(items[i] != used_terrain && !is_village(items[i]) && !is_keep(items[i])) {
|
||||
if(items[i] != used_terrain && !is_village(items[i]) && !is_keep(items[i]) && !is_castle(items[i])) {
|
||||
const int c = std::count(items+i+1,items+nitems,items[i]) + 1;
|
||||
if(c > terrain_count) {
|
||||
used_terrain = items[i];
|
||||
|
|
|
@ -168,7 +168,7 @@ void multiplayer_game_setup_dialog::set_area(const SDL_Rect& area)
|
|||
int height = int(area.h);
|
||||
const int left = area.x;
|
||||
const int top = area.y;
|
||||
const int border_size = 5;
|
||||
const int border_size = 6;
|
||||
const int right = left + width;
|
||||
const int bottom = top + height;
|
||||
|
||||
|
@ -197,7 +197,7 @@ void multiplayer_game_setup_dialog::set_area(const SDL_Rect& area)
|
|||
SDL_Rect rect;
|
||||
|
||||
//the sliders and other options on the right side of the dialog
|
||||
rect.x = xpos + minimap_width + maps_menu_->width() + border_size*2;
|
||||
rect.x = xpos + minimap_width + maps_menu_->width() + border_size;
|
||||
rect.y = ypos;
|
||||
rect.w = maximum<int>(0,right - border_size - rect.x);
|
||||
//a font sized "12" isn't necessarily 12 pixel high.
|
||||
|
@ -205,38 +205,38 @@ void multiplayer_game_setup_dialog::set_area(const SDL_Rect& area)
|
|||
|
||||
turns_restorer_ = surface_restorer(&disp_.video(),rect);
|
||||
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
turns_slider_->set_location(rect);
|
||||
turns_slider_->set_dirty();
|
||||
|
||||
//Village Gold
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
village_gold_restorer_ = surface_restorer(&disp_.video(),rect);
|
||||
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
village_gold_slider_->set_location(rect);
|
||||
village_gold_slider_->set_dirty();
|
||||
|
||||
//Experience Modifier
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
xp_restorer_ = surface_restorer(&disp_.video(),rect);
|
||||
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
xp_modifier_slider_->set_location(rect);
|
||||
xp_modifier_slider_->set_dirty();
|
||||
|
||||
//FOG of war
|
||||
rect.y += rect.h + border_size*2;
|
||||
rect.y += rect.h + border_size + 1;
|
||||
|
||||
fog_game_->set_location(rect.x,rect.y);
|
||||
fog_game_->set_dirty();
|
||||
|
||||
rect.y += fog_game_->location().h + border_size;
|
||||
rect.y += fog_game_->location().h + border_size + 1;
|
||||
|
||||
//Shroud
|
||||
shroud_game_->set_location(rect.x,rect.y);
|
||||
|
@ -256,11 +256,16 @@ void multiplayer_game_setup_dialog::set_area(const SDL_Rect& area)
|
|||
|
||||
rect.y += vision_combo_->height() + border_size;
|
||||
|
||||
gui::button* left_button = launch_game_;
|
||||
gui::button* right_button = cancel_game_;
|
||||
|
||||
#ifdef OK_BUTTON_ON_RIGHT
|
||||
std::swap(left_button,right_button);
|
||||
#endif
|
||||
|
||||
//Buttons
|
||||
cancel_game_->set_location(right - cancel_game_->width() - gui::ButtonHPadding,
|
||||
bottom - cancel_game_->height() - gui::ButtonVPadding);
|
||||
launch_game_->set_location(right - cancel_game_->width() - launch_game_->width() - gui::ButtonHPadding*2,
|
||||
bottom - launch_game_->height() - gui::ButtonVPadding);
|
||||
right_button->set_location(right - right_button->width() - gui::ButtonHPadding,bottom - right_button->height() - gui::ButtonVPadding);
|
||||
left_button->set_location(right - right_button->width() - left_button->width() - gui::ButtonHPadding*2,bottom - left_button->height() - gui::ButtonVPadding);
|
||||
|
||||
cancel_game_->set_dirty();
|
||||
launch_game_->set_dirty();
|
||||
|
|
|
@ -343,9 +343,16 @@ void mp_connect::set_area(const SDL_Rect& rect)
|
|||
// Wait to players, Configure players
|
||||
//gui::draw_dialog_background(left, right, width, height, *disp_, "menu");
|
||||
|
||||
gui::button* left_button = &launch_;
|
||||
gui::button* right_button = &cancel_;
|
||||
|
||||
#ifdef OK_BUTTON_ON_RIGHT
|
||||
std::swap(left_button,right_button);
|
||||
#endif
|
||||
|
||||
//Buttons
|
||||
cancel_.set_location(right - cancel_.width() - gui::ButtonHPadding,bottom-cancel_.height()-gui::ButtonVPadding);
|
||||
launch_.set_location(right - cancel_.width() - launch_.width() - gui::ButtonHPadding*2,bottom-launch_.height()-gui::ButtonVPadding);
|
||||
right_button->set_location(right - right_button->width() - gui::ButtonHPadding,bottom-right_button->height()-gui::ButtonVPadding);
|
||||
left_button->set_location(right - right_button->width() - left_button->width() - gui::ButtonHPadding*2,bottom-left_button->height()-gui::ButtonVPadding);
|
||||
|
||||
ai_.set_location(left+30,bottom-60);
|
||||
|
||||
|
@ -589,10 +596,10 @@ lobby::RESULT mp_connect::process()
|
|||
side["description"] = preferences::login();
|
||||
for(size_t m = 0; m != combos_type_.size(); ++m) {
|
||||
if(m != n) {
|
||||
if(combos_type_[m].selected() == 4){
|
||||
combos_type_[m].set_selected(0);
|
||||
if(combos_type_[m].selected() == 5){
|
||||
combos_type_[m].set_selected(2);
|
||||
config& si = **(sides.first+m);
|
||||
si["controller"] = "network";
|
||||
si["controller"] = "ai";
|
||||
si["description"] = "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -487,7 +487,7 @@ void set_default_send_size(size_t max_size)
|
|||
default_max_send_size = max_size;
|
||||
}
|
||||
|
||||
void send_data(const config& cfg, connection connection_num, size_t max_size)
|
||||
void send_data(const config& cfg, connection connection_num, size_t max_size, SEND_TYPE mode)
|
||||
{
|
||||
if(cfg.empty()) {
|
||||
return;
|
||||
|
@ -533,7 +533,7 @@ void send_data(const config& cfg, connection connection_num, size_t max_size)
|
|||
|
||||
//if the data is less than our maximum chunk, and there is no data queued to send
|
||||
//to this host, then send all data now
|
||||
if((max_size == 0 || value.size()+1 <= max_size) && send_queue.count(connection_num) == 0) {
|
||||
if(mode == SEND_DATA && (max_size == 0 || value.size()+1 <= max_size) && send_queue.count(connection_num) == 0) {
|
||||
std::cerr << "sending " << (value.size()+1) << " bytes\n";
|
||||
const int res = SDLNet_TCP_Send(get_socket(connection_num),
|
||||
const_cast<char*>(value.c_str()),
|
||||
|
@ -553,10 +553,17 @@ void send_data(const config& cfg, connection connection_num, size_t max_size)
|
|||
std::copy(value.begin(),value.end(),itor->second.buf.begin());
|
||||
itor->second.buf.back() = 0;
|
||||
|
||||
process_send_queue(connection_num,max_size);
|
||||
if(mode == SEND_DATA) {
|
||||
process_send_queue(connection_num,max_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void queue_data(const config& cfg, connection connection_num)
|
||||
{
|
||||
send_data(cfg,connection_num,0,QUEUE_ONLY);
|
||||
}
|
||||
|
||||
void process_send_queue(connection connection_num, size_t max_size)
|
||||
{
|
||||
if(connection_num == 0) {
|
||||
|
@ -595,6 +602,8 @@ void process_send_queue(connection connection_num, size_t max_size)
|
|||
throw error("Sending queued data failed",connection_num);
|
||||
}
|
||||
|
||||
std::cerr << "sent.\n";
|
||||
|
||||
upto += bytes_to_send;
|
||||
|
||||
//if we've now sent the entire item, erase it from the send queue
|
||||
|
|
|
@ -74,6 +74,8 @@ connection receive_data(config& cfg, connection connection_num=0, int timeout=0)
|
|||
//sets the default maximum number of bytes to send to a client at a time
|
||||
void set_default_send_size(size_t send_size);
|
||||
|
||||
enum SEND_TYPE { SEND_DATA, QUEUE_ONLY };
|
||||
|
||||
//function to send data down a given connection, or broadcast
|
||||
//to all peers if connection_num is 0. throws error.
|
||||
//it will send a maximum of 'max_size' bytes. If cfg when serialized is more than
|
||||
|
@ -82,9 +84,15 @@ void set_default_send_size(size_t send_size);
|
|||
//appended to the send queue, and max_size bytes in the send queue will be sent.
|
||||
//if 'max_size' is 0, then the entire contents of the send_queue as well as 'cfg'
|
||||
//will be sent.
|
||||
//if 'mode' is set to 'QUEUE_ONLY', then no data will be sent at all: only placed
|
||||
//in the send queue. This will guarantee that this function never throws
|
||||
//network::error exceptions
|
||||
//
|
||||
//data in the send queue can be sent using process_send_queue
|
||||
void send_data(const config& cfg, connection connection_num=0, size_t max_size=0);
|
||||
void send_data(const config& cfg, connection connection_num=0, size_t max_size=0, SEND_TYPE mode=SEND_DATA);
|
||||
|
||||
//function to queue data to be sent. queue_data(cfg,sock) is equivalent to send_data(cfg,sock,0,QUEUE_ONLY)
|
||||
void queue_data(const config& cfg, connection connection_num=0);
|
||||
|
||||
//function to send any data that is in a connection's send_queue, up to a maximum
|
||||
//of 'max_size' bytes -- or the entire send queue if 'max_size' bytes is 0
|
||||
|
|
|
@ -936,6 +936,7 @@ bool turn_info::can_execute_command(hotkey::HOTKEY_COMMAND command) const
|
|||
case hotkey::HOTKEY_SPEAK:
|
||||
case hotkey::HOTKEY_SPEAK_ALLY:
|
||||
case hotkey::HOTKEY_SPEAK_ALL:
|
||||
case hotkey::HOTKEY_CHAT_LOG:
|
||||
return network::nconnections() > 0;
|
||||
|
||||
case hotkey::HOTKEY_REDO:
|
||||
|
@ -1722,10 +1723,12 @@ void turn_info::recall()
|
|||
<< string_table["xp"] << ": "
|
||||
<< u->experience() << "/";
|
||||
|
||||
if(u->type().advances_to().empty())
|
||||
if(u->can_advance() == false) {
|
||||
option << "-";
|
||||
else
|
||||
} else {
|
||||
option << u->max_experience();
|
||||
}
|
||||
|
||||
options.push_back(option.str());
|
||||
}
|
||||
|
||||
|
@ -1787,7 +1790,6 @@ bool turn_info::has_friends() const
|
|||
|
||||
void turn_info::speak()
|
||||
{
|
||||
|
||||
create_textbox(floating_textbox::TEXTBOX_MESSAGE,string_table["message"] + ":", has_friends() ? string_table["speak_allies_only"] : "", preferences::message_private());
|
||||
}
|
||||
|
||||
|
@ -1885,7 +1887,7 @@ void turn_info::unit_list()
|
|||
<< "/" << i->second.max_hitpoints() << ","
|
||||
<< i->second.experience() << "/";
|
||||
|
||||
if(i->second.type().advances_to().empty())
|
||||
if(i->second.can_advance() == false)
|
||||
row << "-";
|
||||
else
|
||||
row << i->second.max_experience();
|
||||
|
@ -2027,6 +2029,12 @@ void turn_info::show_help()
|
|||
help::show_help(gui_);
|
||||
}
|
||||
|
||||
void turn_info::show_chat_log()
|
||||
{
|
||||
std::string text = recorder.build_chat_log(teams_[gui_.viewing_team()].team_name());
|
||||
gui::show_dialog(gui_,NULL,string_table["chat_log"],"",gui::CLOSE_ONLY,NULL,NULL,"",&text);
|
||||
}
|
||||
|
||||
void turn_info::do_search(const std::string& new_search)
|
||||
{
|
||||
if(new_search.empty() == false && new_search != last_search_)
|
||||
|
|
|
@ -152,6 +152,7 @@ private:
|
|||
virtual void continue_move();
|
||||
virtual void search();
|
||||
virtual void show_help();
|
||||
virtual void show_chat_log();
|
||||
virtual hotkey::ACTION_STATE get_action_state(hotkey::HOTKEY_COMMAND command) const;
|
||||
|
||||
void do_search(const std::string& str);
|
||||
|
|
|
@ -376,6 +376,30 @@ void replay::speak(const config& cfg)
|
|||
}
|
||||
}
|
||||
|
||||
std::string replay::build_chat_log(const std::string& team) const
|
||||
{
|
||||
std::stringstream str;
|
||||
const config::child_list& cmd = commands();
|
||||
for(config::child_list::const_iterator i = cmd.begin(); i != cmd.end(); ++i) {
|
||||
const config* speak = (**i).child("speak");
|
||||
if(speak != NULL) {
|
||||
const config& cfg = *speak;
|
||||
const std::string& team_name = cfg["team_name"];
|
||||
if(team_name == "" || team_name == team) {
|
||||
if(team_name == "") {
|
||||
str << "<" << cfg["description"] << "> ";
|
||||
} else {
|
||||
str << "*" << cfg["description"] << "* ";
|
||||
}
|
||||
|
||||
str << cfg["message"] << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
config replay::get_data_range(int cmd_start, int cmd_end, DATA_TYPE data_type)
|
||||
{
|
||||
log_scope("get_data_range\n");
|
||||
|
@ -844,13 +868,11 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
u = units.find(src);
|
||||
tgt = units.find(dst);
|
||||
|
||||
if(u != units.end() && u->second.advances() &&
|
||||
u->second.type().advances_to().empty() == false) {
|
||||
if(u != units.end() && u->second.advances()) {
|
||||
advancing_units.push_back(u->first);
|
||||
}
|
||||
|
||||
if(tgt != units.end() && tgt->second.advances() &&
|
||||
tgt->second.type().advances_to().empty() == false) {
|
||||
if(tgt != units.end() && tgt->second.advances()) {
|
||||
advancing_units.push_back(tgt->first);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
void end_turn();
|
||||
|
||||
void speak(const config& cfg);
|
||||
std::string build_chat_log(const std::string& team) const;
|
||||
|
||||
//get data range will get a range of moves from the replay system.
|
||||
//if data_type is 'ALL_DATA' then it will return all data in this range
|
||||
|
|
|
@ -153,7 +153,7 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
|
||||
break;
|
||||
case UNIT_XP:
|
||||
if(u->second.type().advances_to().empty()) {
|
||||
if(u->second.can_advance() == false) {
|
||||
str << u->second.experience() << "/-";
|
||||
} else {
|
||||
//if killing a unit of the same level as us lets us advance, display in 'good' colour
|
||||
|
|
|
@ -59,7 +59,6 @@ SDL_Surface* make_neutral_surface(SDL_Surface* surf)
|
|||
}
|
||||
|
||||
SDL_Surface* const result = SDL_ConvertSurface(surf,&get_neutral_pixel_format(),SDL_SWSURFACE);
|
||||
invalidate_sdl_surface_cache(surf);
|
||||
if(result != NULL) {
|
||||
SDL_SetAlpha(result,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
|
||||
}
|
||||
|
@ -75,13 +74,12 @@ int sdl_add_ref(SDL_Surface* surface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SDL_Surface* clone_surface(SDL_Surface* surface)
|
||||
SDL_Surface* create_optimized_surface(SDL_Surface* surface)
|
||||
{
|
||||
if(surface == NULL)
|
||||
return NULL;
|
||||
|
||||
SDL_Surface* const result = display_format_alpha(surface);
|
||||
invalidate_sdl_surface_cache(surface);
|
||||
if(result == surface) {
|
||||
std::cerr << "resulting surface is the same as the source!!!\n";
|
||||
}
|
||||
|
@ -135,7 +133,7 @@ SDL_Surface* scale_surface(SDL_Surface* surface, int w, int h)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(dst);
|
||||
return create_optimized_surface(dst);
|
||||
}
|
||||
|
||||
SDL_Surface* scale_surface_blended(SDL_Surface* surface, int w, int h)
|
||||
|
@ -212,13 +210,13 @@ SDL_Surface* scale_surface_blended(SDL_Surface* surface, int w, int h)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(dst);
|
||||
return create_optimized_surface(dst);
|
||||
}
|
||||
|
||||
SDL_Surface* adjust_surface_colour(SDL_Surface* surface, int r, int g, int b)
|
||||
{
|
||||
if(r == 0 && g == 0 && b == 0 || surface == NULL)
|
||||
return clone_surface(surface);
|
||||
return create_optimized_surface(surface);
|
||||
|
||||
scoped_sdl_surface surf(make_neutral_surface(surface));
|
||||
|
||||
|
@ -246,7 +244,7 @@ SDL_Surface* adjust_surface_colour(SDL_Surface* surface, int r, int g, int b)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* greyscale_image(SDL_Surface* surface)
|
||||
|
@ -286,7 +284,7 @@ SDL_Surface* greyscale_image(SDL_Surface* surface)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* brighten_image(SDL_Surface* surface, double amount)
|
||||
|
@ -321,7 +319,7 @@ SDL_Surface* brighten_image(SDL_Surface* surface, double amount)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* adjust_surface_alpha(SDL_Surface* surface, double amount)
|
||||
|
@ -354,7 +352,7 @@ SDL_Surface* adjust_surface_alpha(SDL_Surface* surface, double amount)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* adjust_surface_alpha_add(SDL_Surface* surface, int amount)
|
||||
|
@ -387,7 +385,7 @@ SDL_Surface* adjust_surface_alpha_add(SDL_Surface* surface, int amount)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
// Applies a mask on a surface
|
||||
|
@ -431,7 +429,7 @@ SDL_Surface* mask_surface(SDL_Surface* surface, SDL_Surface* mask)
|
|||
}
|
||||
|
||||
return surf;
|
||||
//return clone_surface(surf);
|
||||
//return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
// Cuts a rectangle from a surface.
|
||||
|
@ -503,7 +501,7 @@ SDL_Surface* blend_surface(SDL_Surface* surface, double amount, Uint32 colour)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* flip_surface(SDL_Surface* surface)
|
||||
|
@ -532,7 +530,7 @@ SDL_Surface* flip_surface(SDL_Surface* surface)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* flop_surface(SDL_Surface* surface)
|
||||
|
@ -561,7 +559,7 @@ SDL_Surface* flop_surface(SDL_Surface* surface)
|
|||
}
|
||||
}
|
||||
|
||||
return clone_surface(surf);
|
||||
return create_optimized_surface(surf);
|
||||
}
|
||||
|
||||
SDL_Surface* create_compatible_surface(SDL_Surface* surf, int width, int height)
|
||||
|
@ -622,7 +620,7 @@ SDL_Surface* get_surface_portion(SDL_Surface* src, SDL_Rect& area)
|
|||
|
||||
SDL_Rect dstarea = {0,0,0,0};
|
||||
|
||||
sdl_safe_blit(src,&area,dst,&dstarea);
|
||||
SDL_BlitSurface(src,&area,dst,&dstarea);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
@ -745,7 +743,7 @@ surface_restorer::~surface_restorer()
|
|||
void surface_restorer::restore()
|
||||
{
|
||||
if(surface_ != NULL) {
|
||||
sdl_safe_blit(surface_,NULL,target_->getSurface(),&rect_);
|
||||
SDL_BlitSurface(surface_,NULL,target_->getSurface(),&rect_);
|
||||
update_rect(rect_);
|
||||
}
|
||||
}
|
||||
|
@ -761,23 +759,4 @@ void surface_restorer::update()
|
|||
void surface_restorer::cancel()
|
||||
{
|
||||
surface_.assign(NULL);
|
||||
}
|
||||
|
||||
//dummy definition of this SDL-private data structure, so that we can clear
|
||||
//the surface's cache
|
||||
struct SDL_BlitMap {
|
||||
SDL_Surface* dst;
|
||||
};
|
||||
|
||||
void invalidate_sdl_surface_cache(SDL_Surface* surf)
|
||||
{
|
||||
if(surf->map->dst != get_video_surface()) {
|
||||
surf->map->dst = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_safe_blit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect)
|
||||
{
|
||||
SDL_BlitSurface(src,srcrect,dst,dstrect);
|
||||
invalidate_sdl_surface_cache(src);
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ int sdl_add_ref(SDL_Surface* surface);
|
|||
typedef util::scoped_resource<SDL_Surface*,free_sdl_surface> scoped_sdl_surface;
|
||||
|
||||
SDL_Surface* make_neutral_surface(SDL_Surface* surf);
|
||||
SDL_Surface* clone_surface(SDL_Surface* surface);
|
||||
SDL_Surface* create_optimized_surface(SDL_Surface* surface);
|
||||
SDL_Surface* scale_surface(SDL_Surface* surface, int w, int h);
|
||||
SDL_Surface* scale_surface_blended(SDL_Surface* surface, int w, int h);
|
||||
SDL_Surface* adjust_surface_colour(SDL_Surface* surface, int r, int g, int b);
|
||||
|
@ -212,14 +212,4 @@ private:
|
|||
SDL_Rect rect;
|
||||
};
|
||||
|
||||
//SDL 1.2.x has a bug where after a blit, a surface stores the surface it was last
|
||||
//blitted to. This is a problem, because if the surface is freed, and then a new
|
||||
//one created in the same memory location, it will think its blitter knows how to
|
||||
//blit to that surface when it doesn't.
|
||||
//
|
||||
//This function will invalidate the cache, to keep the problem from occurring.
|
||||
void invalidate_sdl_surface_cache(SDL_Surface* surf);
|
||||
|
||||
void sdl_safe_blit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -134,7 +134,7 @@ bool game::take_side(network::connection player, const config& cfg)
|
|||
config& reassign = response.add_child("reassign_side");
|
||||
reassign["from"] = cfg["side"];
|
||||
reassign["to"] = new_cfg["side"];
|
||||
network::send_data(response,player);
|
||||
network::queue_data(response,player);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -147,7 +147,7 @@ bool game::take_side(network::connection player, const config& cfg)
|
|||
|
||||
//send host notification of taking this side
|
||||
if(players_.empty() == false) {
|
||||
network::send_data(cfg,players_.front());
|
||||
network::queue_data(cfg,players_.front());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -236,7 +236,7 @@ void game::add_player(network::connection player)
|
|||
//tell this player that the game has started
|
||||
config cfg;
|
||||
cfg.add_child("start_game");
|
||||
network::send_data(cfg,player);
|
||||
network::queue_data(cfg,player);
|
||||
}
|
||||
|
||||
//if the player is already in the game, don't add them.
|
||||
|
@ -249,7 +249,7 @@ void game::add_player(network::connection player)
|
|||
send_user_list();
|
||||
|
||||
//send the player the history of the game to-date
|
||||
network::send_data(history_,player);
|
||||
network::queue_data(history_,player);
|
||||
}
|
||||
|
||||
void game::remove_player(network::connection player)
|
||||
|
@ -266,7 +266,7 @@ void game::remove_player(network::connection player)
|
|||
if(players_.empty() == false) {
|
||||
config drop;
|
||||
drop["side_drop"] = side->second;
|
||||
network::send_data(drop,players_.front());
|
||||
network::queue_data(drop,players_.front());
|
||||
}
|
||||
|
||||
sides_taken_.erase(side->second);
|
||||
|
@ -319,7 +319,7 @@ void game::send_data(const config& data, network::connection exclude)
|
|||
for(std::vector<network::connection>::const_iterator
|
||||
i = players_.begin(); i != players_.end(); ++i) {
|
||||
if(*i != exclude && (allow_observers_ || sides_.count(*i) == 1)) {
|
||||
network::send_data(data,*i);
|
||||
network::queue_data(data,*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ void game::send_data_team(const config& data, const std::string& team, network::
|
|||
{
|
||||
for(std::vector<network::connection>::const_iterator i = players_.begin(); i != players_.end(); ++i) {
|
||||
if(*i != exclude && player_on_team(team,*i)) {
|
||||
network::send_data(data,*i);
|
||||
network::queue_data(data,*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,14 +90,22 @@ void server::run()
|
|||
config& gamelist = initial_response_.add_child("gamelist");
|
||||
old_initial_response_ = initial_response_;
|
||||
|
||||
bool sync_scheduled = false;
|
||||
for(int loop = 0;; ++loop) {
|
||||
try {
|
||||
if(sync_scheduled) {
|
||||
//send all players the information that a player has logged
|
||||
//out of the system
|
||||
lobby_players_.send_data(sync_initial_response());
|
||||
sync_scheduled = false;
|
||||
}
|
||||
|
||||
|
||||
//make sure we log stats every 5 minutes
|
||||
if((loop%100) == 0 && last_stats_+5*60 < time(NULL)) {
|
||||
dump_stats();
|
||||
}
|
||||
|
||||
|
||||
network::process_send_queue();
|
||||
|
||||
network::connection sock = network::accept_connection();
|
||||
|
@ -500,9 +508,7 @@ void server::run()
|
|||
e.disconnect();
|
||||
}
|
||||
|
||||
//send all players the information that a player has logged
|
||||
//out of the system
|
||||
lobby_players_.send_data(sync_initial_response());
|
||||
sync_scheduled = true;
|
||||
|
||||
std::cerr << "done closing socket...\n";
|
||||
}
|
||||
|
@ -570,7 +576,7 @@ int main(int argc, char** argv)
|
|||
try {
|
||||
server(port).run();
|
||||
} catch(network::error& e) {
|
||||
std::cerr << "error starting server: " << e.message << "\n";
|
||||
std::cerr << "caught network error while server was running. aborting.: " << e.message << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ SDL_Rect draw_dialog_title(int x, int y, display* disp, const std::string& text)
|
|||
|
||||
void draw_dialog(int x, int y, int w, int h, display& disp, const std::string& title,
|
||||
const std::string* style, std::vector<button*>* buttons,
|
||||
surface_restorer* restorer)
|
||||
surface_restorer* restorer, button* help_button)
|
||||
{
|
||||
int border_size = 10;
|
||||
SDL_Rect title_area = {0,0,0,0};
|
||||
|
@ -209,9 +209,16 @@ void draw_dialog(int x, int y, int w, int h, display& disp, const std::string& t
|
|||
buttons_area.w += ButtonHPadding;
|
||||
}
|
||||
|
||||
size_t buttons_width = buttons_area.w;
|
||||
|
||||
if(help_button != NULL) {
|
||||
buttons_width += help_button->width() + ButtonHPadding*2;
|
||||
buttons_area.y = y + h;
|
||||
}
|
||||
|
||||
const int xpos = x;
|
||||
const int ypos = y - int(title_area.h);
|
||||
const int width = maximum<int>(w,maximum<int>(int(title_area.w),int(buttons_area.w)));
|
||||
const int width = maximum<int>(w,maximum<int>(int(title_area.w),int(buttons_width)));
|
||||
const int height = title_area.h + buttons_area.h + h;
|
||||
|
||||
buttons_area.x += xpos + width;
|
||||
|
@ -223,11 +230,19 @@ void draw_dialog(int x, int y, int w, int h, display& disp, const std::string& t
|
|||
}
|
||||
|
||||
if(buttons != NULL) {
|
||||
#ifdef OK_BUTTON_ON_RIGHT
|
||||
std::reverse(buttons->begin(),buttons->end());
|
||||
#endif
|
||||
|
||||
for(std::vector<button*>::const_iterator b = buttons->begin(); b != buttons->end(); ++b) {
|
||||
(**b).set_location(buttons_area.x,buttons_area.y);
|
||||
buttons_area.x += (**b).width() + ButtonHPadding;
|
||||
}
|
||||
}
|
||||
|
||||
if(help_button != NULL) {
|
||||
help_button->set_location(x+ButtonHPadding,buttons_area.y);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_rectangle(int x, int y, int w, int h, Uint32 colour,SDL_Surface* target)
|
||||
|
@ -379,18 +394,23 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
SDL_Rect clipRect = disp.screen_area();
|
||||
|
||||
const bool use_textbox = text_widget_text != NULL;
|
||||
const bool editable_textbox = use_textbox && std::find(text_widget_text->begin(),text_widget_text->end(),'\n') == text_widget_text->end();
|
||||
static const std::string default_text_string = "";
|
||||
const unsigned int text_box_width = 350;
|
||||
textbox text_widget(disp,text_box_width,
|
||||
use_textbox ? *text_widget_text : default_text_string);
|
||||
use_textbox ? *text_widget_text : default_text_string, editable_textbox);
|
||||
|
||||
int text_widget_width = 0;
|
||||
int text_widget_height = 0;
|
||||
if(use_textbox) {
|
||||
text_widget_width =
|
||||
font::draw_text(NULL, clipRect, message_font_size,
|
||||
font::NORMAL_COLOUR, text_widget_label, 0, 0, NULL).w +
|
||||
text_widget.location().w;
|
||||
|
||||
text_widget.set_wrap(!editable_textbox);
|
||||
|
||||
const SDL_Rect& area = font::text_area(*text_widget_text,message_font_size);
|
||||
|
||||
text_widget.set_width(minimum<size_t>(disp.x()/2,maximum<size_t>(area.w,text_widget.location().w)));
|
||||
text_widget.set_height(minimum<size_t>(disp.y()/2,maximum<size_t>(area.h,text_widget.location().h)));
|
||||
text_widget_width = font::text_area(text_widget_label,message_font_size).w + text_widget.location().w;;
|
||||
text_widget_height = text_widget.location().h + 16;
|
||||
}
|
||||
|
||||
|
@ -580,19 +600,15 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
buttons_ptr.push_back(&*bt);
|
||||
}
|
||||
|
||||
button help_button(disp,string_table["action_help"]);
|
||||
if(help_topic.empty() == false) {
|
||||
buttons_ptr.push_back(&help_button);
|
||||
}
|
||||
|
||||
|
||||
frame_width += left_preview_pane_width + right_preview_pane_width;
|
||||
frame_height += above_preview_pane_height;
|
||||
|
||||
surface_restorer restorer;
|
||||
|
||||
button help_button(disp,string_table["action_help"]);
|
||||
|
||||
const std::string& title = image == NULL ? caption : "";
|
||||
draw_dialog(xframe,yframe,frame_width,frame_height,disp,title,dialog_style,&buttons_ptr,&restorer);
|
||||
draw_dialog(xframe,yframe,frame_width,frame_height,disp,title,dialog_style,&buttons_ptr,&restorer,help_topic.empty() ? NULL : &help_button);
|
||||
|
||||
//calculate the positions of the preview panes to the sides of the dialog
|
||||
if(preview_panes != NULL) {
|
||||
|
|
|
@ -71,7 +71,7 @@ SDL_Rect draw_dialog_title(int x, int y, display* disp, const std::string& text)
|
|||
//to its original state after the dialog is drawn.
|
||||
void draw_dialog(int x, int y, int w, int h, display& disp, const std::string& title,
|
||||
const std::string* dialog_style=NULL, std::vector<button*>* buttons=NULL,
|
||||
surface_restorer* restorer=NULL);
|
||||
surface_restorer* restorer=NULL, button* help_button=NULL);
|
||||
|
||||
class dialog_action
|
||||
{
|
||||
|
|
71
src/unit.cpp
71
src/unit.cpp
|
@ -27,9 +27,9 @@
|
|||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
const std::string ModificationTypes[] = { "object", "trait" };
|
||||
const int NumModificationTypes = sizeof(ModificationTypes)/
|
||||
sizeof(*ModificationTypes);
|
||||
const std::string ModificationTypes[] = { "object", "trait", "advance" };
|
||||
const size_t NumModificationTypes = sizeof(ModificationTypes)/
|
||||
sizeof(*ModificationTypes);
|
||||
}
|
||||
|
||||
bool compare_unit_values::operator()(const unit& a, const unit& b) const
|
||||
|
@ -349,14 +349,12 @@ int unit::max_experience() const
|
|||
bool unit::get_experience(int xp)
|
||||
{
|
||||
experience_ += xp;
|
||||
if(experience_ > max_experience())
|
||||
experience_ = max_experience();
|
||||
return advances();
|
||||
}
|
||||
|
||||
bool unit::advances() const
|
||||
{
|
||||
return experience_ >= max_experience() && !type().advances_to().empty();
|
||||
return experience_ >= max_experience() && can_advance();
|
||||
}
|
||||
|
||||
bool unit::gets_hit(int damage)
|
||||
|
@ -801,15 +799,24 @@ const std::string& unit::image() const
|
|||
switch(state_) {
|
||||
case STATE_NORMAL: return type_->image();
|
||||
case STATE_DEFENDING_LONG:
|
||||
return type_->image_defensive(attack_type::LONG_RANGE);
|
||||
case STATE_DEFENDING_SHORT:
|
||||
return type_->image_defensive(attack_type::SHORT_RANGE);
|
||||
case STATE_DEFENDING_SHORT: {
|
||||
const attack_type::RANGE range = (state_ == STATE_DEFENDING_LONG) ? attack_type::LONG_RANGE : attack_type::SHORT_RANGE;
|
||||
const unit_animation* const anim = type_->defend_animation(getsHit_,range);
|
||||
if(anim != NULL) {
|
||||
const std::string* img = anim->get_frame(attackingMilliseconds_);
|
||||
if(img != NULL) {
|
||||
return *img;
|
||||
}
|
||||
}
|
||||
|
||||
return type_->image_defensive(range);
|
||||
}
|
||||
case STATE_ATTACKING: {
|
||||
if(attackType_ == NULL)
|
||||
return type_->image();
|
||||
|
||||
const std::string* const img =
|
||||
attackType_->get_frame(attackingMilliseconds_);
|
||||
attackType_->animation().get_frame(attackingMilliseconds_);
|
||||
|
||||
if(img == NULL)
|
||||
return type_->image_fighting(attackType_->range());
|
||||
|
@ -825,10 +832,12 @@ const std::string& unit::image() const
|
|||
}
|
||||
}
|
||||
|
||||
void unit::set_defending(bool newval, attack_type::RANGE range)
|
||||
void unit::set_defending(bool newval, bool hits, int ms, attack_type::RANGE range)
|
||||
{
|
||||
state_ = newval ? (range == attack_type::LONG_RANGE ? STATE_DEFENDING_LONG :
|
||||
STATE_DEFENDING_SHORT): STATE_NORMAL;
|
||||
attackingMilliseconds_ = ms;
|
||||
getsHit_ = hits;
|
||||
}
|
||||
|
||||
void unit::set_attacking(bool newval, const attack_type* type, int ms)
|
||||
|
@ -883,6 +892,37 @@ void unit::set_goto(const gamemap::location& new_goto)
|
|||
goto_ = new_goto;
|
||||
}
|
||||
|
||||
bool unit::can_advance() const
|
||||
{
|
||||
return type().can_advance() || get_modification_advances().empty() == false;
|
||||
}
|
||||
|
||||
config::child_list unit::get_modification_advances() const
|
||||
{
|
||||
config::child_list res;
|
||||
const config::child_list& advances = type().modification_advancements();
|
||||
for(config::child_list::const_iterator i = advances.begin(); i != advances.end(); ++i) {
|
||||
if(modification_count("advance",(**i)["id"]) < lexical_cast_default<size_t>((**i)["max_times"],1)) {
|
||||
res.push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t unit::modification_count(const std::string& type, const std::string& id) const
|
||||
{
|
||||
size_t res = 0;
|
||||
const config::child_list& items = modifications_.get_children(type);
|
||||
for(config::child_list::const_iterator i = items.begin(); i != items.end(); ++i) {
|
||||
if((**i)["id"] == id) {
|
||||
++res;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void unit::add_modification(const std::string& type,
|
||||
const config& mod, bool no_add)
|
||||
{
|
||||
|
@ -895,6 +935,15 @@ void unit::add_modification(const std::string& type,
|
|||
for(config::const_child_itors i = mod.child_range("effect");
|
||||
i.first != i.second; ++i.first) {
|
||||
|
||||
//see if the effect only applies to certain unit types
|
||||
const std::string& type_filter = (**i.first)["unit_type"];
|
||||
if(type_filter.empty() == false) {
|
||||
const std::vector<std::string>& types = config::split(type_filter);
|
||||
if(std::find(types.begin(),types.end(),this->type().name()) == types.end()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream description;
|
||||
|
||||
const std::string& apply_to = (**i.first)["apply_to"];
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
//(could be in the middle of an attack etc)
|
||||
const std::string& image() const;
|
||||
|
||||
void set_defending(bool newval,
|
||||
void set_defending(bool newval, bool hits=false, int ms=0,
|
||||
attack_type::RANGE range=attack_type::LONG_RANGE);
|
||||
void set_attacking(bool newval, const attack_type* type=NULL, int ms=0);
|
||||
|
||||
|
@ -134,6 +134,11 @@ public:
|
|||
|
||||
bool is_flying() const;
|
||||
|
||||
bool can_advance() const;
|
||||
config::child_list get_modification_advances() const;
|
||||
|
||||
size_t modification_count(const std::string& type, const std::string& id) const;
|
||||
|
||||
void add_modification(const std::string& type, const config& modification,
|
||||
bool no_add=false);
|
||||
|
||||
|
@ -150,6 +155,7 @@ private:
|
|||
STATE state_;
|
||||
const attack_type* attackType_;
|
||||
int attackingMilliseconds_;
|
||||
bool getsHit_;
|
||||
|
||||
int hitpoints_;
|
||||
int maxHitpoints_, backupMaxHitpoints_;
|
||||
|
|
|
@ -203,8 +203,6 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
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);
|
||||
|
||||
const gamemap::location leader_loc = under_leadership(units,a);
|
||||
unit_map::iterator leader = units.end();
|
||||
if(leader_loc.valid()) {
|
||||
|
@ -215,8 +213,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
|
||||
//the missile frames are based around the time when the missile impacts.
|
||||
//the 'real' frames are based around the time when the missile launches.
|
||||
const int first_missile = minimum<int>(-100,attack.get_first_frame(attack_type::MISSILE_FRAME));
|
||||
const int last_missile = attack.get_last_frame(attack_type::MISSILE_FRAME);
|
||||
const int first_missile = minimum<int>(-100,attack.animation().get_first_frame(unit_animation::MISSILE_FRAME));
|
||||
const int last_missile = attack.animation().get_last_frame(unit_animation::MISSILE_FRAME);
|
||||
|
||||
const int real_last_missile = last_missile - first_missile;
|
||||
const int missile_impact = -first_missile;
|
||||
|
@ -224,17 +222,17 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
const int time_resolution = 20;
|
||||
const int acceleration = disp.turbo() ? 5:1;
|
||||
|
||||
const std::vector<attack_type::sfx>& sounds = attack.sound_effects();
|
||||
std::vector<attack_type::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
const std::vector<unit_animation::sfx>& sounds = attack.animation().sound_effects();
|
||||
std::vector<unit_animation::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
|
||||
const std::string& hit_sound = def->second.type().get_hit_sound();
|
||||
bool played_hit_sound = (hit_sound == "" || hit_sound == "null");
|
||||
const int play_hit_sound_at = 0;
|
||||
|
||||
const bool hits = damage > 0;
|
||||
const int begin_at = attack.get_first_frame();
|
||||
const int begin_at = attack.animation().get_first_frame();
|
||||
const int end_at = maximum((damage+1)*time_resolution+missile_impact,
|
||||
maximum(attack.get_last_frame(),real_last_missile));
|
||||
maximum(attack.animation().get_last_frame(),real_last_missile));
|
||||
|
||||
const double xsrc = disp.get_location_x(a);
|
||||
const double ysrc = disp.get_location_y(a);
|
||||
|
@ -246,8 +244,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
|
||||
const bool vflip = b.y > a.y || b.y == a.y && is_even(a.x);
|
||||
const bool hflip = b.x < a.x;
|
||||
const attack_type::FRAME_DIRECTION dir =
|
||||
(a.x == b.x) ? attack_type::VERTICAL:attack_type::DIAGONAL;
|
||||
const unit_animation::FRAME_DIRECTION dir = (a.x == b.x) ? unit_animation::VERTICAL:unit_animation::DIAGONAL;
|
||||
|
||||
bool dead = false;
|
||||
const int drain_speed = 1*acceleration;
|
||||
|
@ -266,6 +263,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
for(int i = begin_at; i < end_at; i += time_resolution*acceleration) {
|
||||
events::pump();
|
||||
|
||||
def->second.set_defending(true,hits,i - missile_impact,attack_type::LONG_RANGE);
|
||||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
|
@ -284,7 +283,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
|
||||
const std::string* new_halo = NULL;
|
||||
int new_halo_x = 0, new_halo_y = 0;
|
||||
const std::string* unit_image = attack.get_frame(i,NULL,attack_type::UNIT_FRAME,attack_type::VERTICAL,&new_halo,&new_halo_x,&new_halo_y);
|
||||
const std::string* unit_image = attack.animation().get_frame(i,NULL,unit_animation::UNIT_FRAME,unit_animation::VERTICAL,&new_halo,&new_halo_x,&new_halo_y);
|
||||
if(att->second.facing_left() == false) {
|
||||
new_halo_x *= -1;
|
||||
}
|
||||
|
@ -354,8 +353,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
|
||||
const std::string* new_halo = NULL;
|
||||
int new_halo_x = 0, new_halo_y = 0;
|
||||
const std::string* missile_image = attack.get_frame(missile_frame,NULL,
|
||||
attack_type::MISSILE_FRAME,dir,&new_halo,&new_halo_x,&new_halo_y);
|
||||
const std::string* missile_image = attack.animation().get_frame(missile_frame,NULL,
|
||||
unit_animation::MISSILE_FRAME,dir,&new_halo,&new_halo_x,&new_halo_y);
|
||||
|
||||
if(att->second.facing_left() == false) {
|
||||
new_halo_x *= -1;
|
||||
|
@ -367,7 +366,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
|||
static const std::string default_missile(game_config::missile_n_image);
|
||||
static const std::string default_diag_missile(game_config::missile_ne_image);
|
||||
if(missile_image == NULL) {
|
||||
if(dir == attack_type::VERTICAL)
|
||||
if(dir == unit_animation::VERTICAL)
|
||||
missile_image = &default_missile;
|
||||
else
|
||||
missile_image = &default_diag_missile;
|
||||
|
@ -523,8 +522,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
|||
}
|
||||
|
||||
const bool hits = damage > 0;
|
||||
const std::vector<attack_type::sfx>& sounds = attack.sound_effects();
|
||||
std::vector<attack_type::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
const std::vector<unit_animation::sfx>& sounds = attack.animation().sound_effects();
|
||||
std::vector<unit_animation::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
|
||||
const std::string& hit_sound = def->second.type().get_hit_sound();
|
||||
bool played_hit_sound = (hit_sound == "" || hit_sound == "null");
|
||||
|
@ -544,9 +543,9 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
|||
leader->second.set_leading(true);
|
||||
}
|
||||
|
||||
const int begin_at = minimum<int>(-200,attack.get_first_frame());
|
||||
const int begin_at = minimum<int>(-200,attack.animation().get_first_frame());
|
||||
const int end_at = maximum<int>((damage+1)*time_resolution,
|
||||
maximum<int>(200,attack.get_last_frame()));
|
||||
maximum<int>(200,attack.animation().get_last_frame()));
|
||||
|
||||
const double xsrc = disp.get_location_x(a);
|
||||
const double ysrc = disp.get_location_y(a);
|
||||
|
@ -583,6 +582,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
|||
for(int i = begin_at; i < end_at; i += time_resolution*acceleration) {
|
||||
events::pump();
|
||||
|
||||
def->second.set_defending(true,hits,i,attack_type::SHORT_RANGE);
|
||||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
|
@ -627,7 +628,6 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
|||
++flash_num;
|
||||
}
|
||||
|
||||
|
||||
disp.draw_tile(b.x,b.y,NULL,defender_alpha,defender_colour);
|
||||
if(leader_loc.valid()) {
|
||||
disp.draw_tile(leader_loc.x,leader_loc.y);
|
||||
|
@ -637,8 +637,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
|||
int new_halo_x = 0, new_halo_y = 0;
|
||||
|
||||
int xoffset = 0;
|
||||
const std::string* unit_image = attack.get_frame(i,&xoffset,attack_type::UNIT_FRAME,attack_type::VERTICAL,
|
||||
&new_halo_image,&new_halo_x,&new_halo_y);
|
||||
const std::string* unit_image = attack.animation().get_frame(i,&xoffset,unit_animation::UNIT_FRAME,unit_animation::VERTICAL,
|
||||
&new_halo_image,&new_halo_x,&new_halo_y);
|
||||
|
||||
if(!attacker.facing_left()) {
|
||||
xoffset *= -1;
|
||||
|
|
|
@ -28,28 +28,8 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
attack_type::attack_type(const config& cfg)
|
||||
unit_animation::unit_animation(const config& cfg)
|
||||
{
|
||||
name_ = cfg["name"];
|
||||
type_ = cfg["type"];
|
||||
special_ = cfg["special"];
|
||||
backstab_ = special_ == "backstab";
|
||||
icon_ = cfg["icon"];
|
||||
if(icon_.empty())
|
||||
icon_ = "attacks/" + name_ + ".png";
|
||||
|
||||
range_ = cfg["range"] == "long" ? LONG_RANGE : SHORT_RANGE;
|
||||
hexes_ = maximum<int>(1,atoi(cfg["hexes"].c_str()));
|
||||
damage_ = atol(cfg["damage"].c_str());
|
||||
num_attacks_ = atol(cfg["number"].c_str());
|
||||
|
||||
attack_weight_ = atof(cfg["attack_weight"].c_str());
|
||||
defense_weight_ = atof(cfg["defense_weight"].c_str());
|
||||
if ( ! attack_weight_ )
|
||||
attack_weight_ = 1.0;
|
||||
if ( ! defense_weight_ )
|
||||
defense_weight_ = 1.0;
|
||||
|
||||
config::const_child_itors range = cfg.child_range("frame");
|
||||
for(; range.first != range.second; ++range.first){
|
||||
const int beg = atoi((**range.first)["begin"].c_str());
|
||||
|
@ -97,6 +77,92 @@ attack_type::attack_type(const config& cfg)
|
|||
}
|
||||
}
|
||||
|
||||
int unit_animation::get_first_frame(unit_animation::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return minimum<int>(frames_[type].front().start,0);
|
||||
}
|
||||
|
||||
int unit_animation::get_last_frame(unit_animation::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return maximum<int>(frames_[type].back().end,0);
|
||||
}
|
||||
|
||||
const std::string* unit_animation::get_frame(int milliseconds, int* xoff,
|
||||
unit_animation::FRAME_TYPE type,
|
||||
unit_animation::FRAME_DIRECTION dir,
|
||||
const std::string** halo, int* halo_x, int* halo_y) const
|
||||
{
|
||||
for(std::vector<frame>::const_iterator i = frames_[type].begin();
|
||||
i != frames_[type].end(); ++i) {
|
||||
if(i->start > milliseconds)
|
||||
return NULL;
|
||||
|
||||
if(i->start <= milliseconds && i->end > milliseconds) {
|
||||
if(xoff != NULL) {
|
||||
*xoff = i->xoffset;
|
||||
}
|
||||
|
||||
if(halo != NULL) {
|
||||
if(i->halo.empty()) {
|
||||
*halo = NULL;
|
||||
} else {
|
||||
*halo = &i->halo;
|
||||
}
|
||||
|
||||
if(halo_x != NULL) {
|
||||
*halo_x = i->halo_x;
|
||||
}
|
||||
|
||||
if(halo_y != NULL) {
|
||||
*halo_y = i->halo_y;
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == DIAGONAL && i->image_diagonal != "") {
|
||||
return &i->image_diagonal;
|
||||
} else {
|
||||
return &i->image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::vector<unit_animation::sfx>& unit_animation::sound_effects() const
|
||||
{
|
||||
return sfx_;
|
||||
}
|
||||
|
||||
attack_type::attack_type(const config& cfg) : animation_(cfg)
|
||||
{
|
||||
name_ = cfg["name"];
|
||||
type_ = cfg["type"];
|
||||
special_ = cfg["special"];
|
||||
backstab_ = special_ == "backstab";
|
||||
icon_ = cfg["icon"];
|
||||
if(icon_.empty())
|
||||
icon_ = "attacks/" + name_ + ".png";
|
||||
|
||||
range_ = cfg["range"] == "long" ? LONG_RANGE : SHORT_RANGE;
|
||||
hexes_ = maximum<int>(1,atoi(cfg["hexes"].c_str()));
|
||||
damage_ = atol(cfg["damage"].c_str());
|
||||
num_attacks_ = atol(cfg["number"].c_str());
|
||||
|
||||
attack_weight_ = atof(cfg["attack_weight"].c_str());
|
||||
defense_weight_ = atof(cfg["defense_weight"].c_str());
|
||||
if ( ! attack_weight_ )
|
||||
attack_weight_ = 1.0;
|
||||
if ( ! defense_weight_ )
|
||||
defense_weight_ = 1.0;
|
||||
}
|
||||
|
||||
const std::string& attack_type::name() const
|
||||
{
|
||||
return name_;
|
||||
|
@ -152,69 +218,6 @@ bool attack_type::backstab() const
|
|||
return backstab_;
|
||||
}
|
||||
|
||||
int attack_type::get_first_frame(attack_type::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return minimum<int>(frames_[type].front().start,0);
|
||||
}
|
||||
|
||||
int attack_type::get_last_frame(attack_type::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return maximum<int>(frames_[type].back().end,0);
|
||||
}
|
||||
|
||||
const std::string* attack_type::get_frame(int milliseconds, int* xoff,
|
||||
attack_type::FRAME_TYPE type,
|
||||
attack_type::FRAME_DIRECTION dir,
|
||||
const std::string** halo, int* halo_x, int* halo_y) const
|
||||
{
|
||||
for(std::vector<frame>::const_iterator i = frames_[type].begin();
|
||||
i != frames_[type].end(); ++i) {
|
||||
if(i->start > milliseconds)
|
||||
return NULL;
|
||||
|
||||
if(i->start <= milliseconds && i->end > milliseconds) {
|
||||
if(xoff != NULL) {
|
||||
*xoff = i->xoffset;
|
||||
}
|
||||
|
||||
if(halo != NULL) {
|
||||
if(i->halo.empty()) {
|
||||
*halo = NULL;
|
||||
} else {
|
||||
*halo = &i->halo;
|
||||
}
|
||||
|
||||
if(halo_x != NULL) {
|
||||
*halo_x = i->halo_x;
|
||||
}
|
||||
|
||||
if(halo_y != NULL) {
|
||||
*halo_y = i->halo_y;
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == DIAGONAL && i->image_diagonal != "") {
|
||||
return &i->image_diagonal;
|
||||
} else {
|
||||
return &i->image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::vector<attack_type::sfx>& attack_type::sound_effects() const
|
||||
{
|
||||
return sfx_;
|
||||
}
|
||||
|
||||
bool attack_type::matches_filter(const config& cfg) const
|
||||
{
|
||||
const std::string& filter_range = cfg["range"];
|
||||
|
@ -549,6 +552,11 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
|
|||
}
|
||||
|
||||
can_advance_ = advances_to().empty() == false;
|
||||
|
||||
const config::child_list& defends = cfg_.get_children("defend");
|
||||
for(config::child_list::const_iterator d = defends.begin(); d != defends.end(); ++d) {
|
||||
defensive_animations_.push_back(defensive_animation(**d));
|
||||
}
|
||||
}
|
||||
|
||||
int unit_type::num_traits() const { return race_->num_traits(); }
|
||||
|
@ -868,6 +876,39 @@ const std::string& unit_type::race() const
|
|||
return race_->name();
|
||||
}
|
||||
|
||||
unit_type::defensive_animation::defensive_animation(const config& cfg) : hits(HIT_OR_MISS), range(SHORT_OR_LONG), animation(cfg)
|
||||
{
|
||||
const std::string& hits_str = cfg["hits"];
|
||||
if(hits_str.empty() == false) {
|
||||
hits = (hits_str == "yes") ? HIT : MISS;
|
||||
}
|
||||
|
||||
const std::string& range_str = cfg["range"];
|
||||
if(range_str.empty() == false) {
|
||||
range = (range_str == "short") ? SHORT : LONG;
|
||||
}
|
||||
}
|
||||
|
||||
bool unit_type::defensive_animation::matches(bool h, attack_type::RANGE r) const
|
||||
{
|
||||
if(hits == HIT && h == false || hits == MISS && h == true || range == SHORT && r == attack_type::LONG_RANGE || range == LONG && r == attack_type::SHORT_RANGE) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const unit_animation* unit_type::defend_animation(bool hits, attack_type::RANGE range) const
|
||||
{
|
||||
for(std::vector<defensive_animation>::const_iterator i = defensive_animations_.begin(); i != defensive_animations_.end(); ++i) {
|
||||
if(i->matches(hits,range)) {
|
||||
return &i->animation;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
game_data::game_data(const config& cfg)
|
||||
{
|
||||
static const std::vector<config*> dummy_traits;
|
||||
|
|
|
@ -21,26 +21,11 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//the 'attack type' is the type of attack, how many times it strikes,
|
||||
//and how much damage it does.
|
||||
class attack_type
|
||||
//a class to describe a unit's animation sequence
|
||||
class unit_animation
|
||||
{
|
||||
public:
|
||||
enum RANGE { SHORT_RANGE, LONG_RANGE };
|
||||
|
||||
attack_type(const config& cfg);
|
||||
const std::string& name() const;
|
||||
const std::string& type() const;
|
||||
const std::string& special() const;
|
||||
const std::string& icon() const;
|
||||
RANGE range() const;
|
||||
int hexes() const;
|
||||
int damage() const;
|
||||
int num_attacks() const;
|
||||
double attack_weight() const;
|
||||
double defense_weight() const;
|
||||
|
||||
bool backstab() const;
|
||||
unit_animation(const config& cfg);
|
||||
|
||||
enum FRAME_TYPE { UNIT_FRAME, MISSILE_FRAME };
|
||||
enum FRAME_DIRECTION { VERTICAL, DIAGONAL };
|
||||
|
@ -64,24 +49,7 @@ public:
|
|||
|
||||
const std::vector<sfx>& sound_effects() const;
|
||||
|
||||
bool matches_filter(const config& cfg) const;
|
||||
bool apply_modification(const config& cfg,std::string* description);
|
||||
private:
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
std::string special_;
|
||||
std::string icon_;
|
||||
RANGE range_;
|
||||
int hexes_;
|
||||
int damage_;
|
||||
int num_attacks_;
|
||||
double attack_weight_;
|
||||
double defense_weight_;
|
||||
|
||||
//caches whether the unit can backstab. This is important
|
||||
//because the AI queries it alot.
|
||||
bool backstab_;
|
||||
|
||||
struct frame {
|
||||
frame(int i1, int i2, const std::string& img, const std::string& halo, int offset, int halo_x, int halo_y)
|
||||
: start(i1), end(i2), xoffset(offset), image(img), halo(halo), halo_x(halo_x), halo_y(halo_y)
|
||||
|
@ -106,6 +74,49 @@ private:
|
|||
std::vector<sfx> sfx_;
|
||||
};
|
||||
|
||||
//the 'attack type' is the type of attack, how many times it strikes,
|
||||
//and how much damage it does.
|
||||
class attack_type
|
||||
{
|
||||
public:
|
||||
enum RANGE { SHORT_RANGE, LONG_RANGE };
|
||||
|
||||
attack_type(const config& cfg);
|
||||
const std::string& name() const;
|
||||
const std::string& type() const;
|
||||
const std::string& special() const;
|
||||
const std::string& icon() const;
|
||||
RANGE range() const;
|
||||
int hexes() const;
|
||||
int damage() const;
|
||||
int num_attacks() const;
|
||||
double attack_weight() const;
|
||||
double defense_weight() const;
|
||||
|
||||
bool backstab() const;
|
||||
|
||||
const unit_animation& animation() const { return animation_; }
|
||||
|
||||
bool matches_filter(const config& cfg) const;
|
||||
bool apply_modification(const config& cfg,std::string* description);
|
||||
private:
|
||||
unit_animation animation_;
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
std::string special_;
|
||||
std::string icon_;
|
||||
RANGE range_;
|
||||
int hexes_;
|
||||
int damage_;
|
||||
int num_attacks_;
|
||||
double attack_weight_;
|
||||
double defense_weight_;
|
||||
|
||||
//caches whether the unit can backstab. This is important
|
||||
//because the AI queries it alot.
|
||||
bool backstab_;
|
||||
};
|
||||
|
||||
class unit_movement_type;
|
||||
|
||||
//the 'unit movement type' is the basic size of the unit - flying, small land,
|
||||
|
@ -176,6 +187,7 @@ public:
|
|||
|
||||
int experience_needed() const;
|
||||
std::vector<std::string> advances_to() const;
|
||||
const config::child_list& modification_advancements() const { return cfg_.get_children("advancement"); }
|
||||
const std::string& usage() const;
|
||||
|
||||
struct experience_accelerator {
|
||||
|
@ -220,6 +232,8 @@ public:
|
|||
|
||||
const std::string& race() const;
|
||||
|
||||
const unit_animation* defend_animation(bool hits, attack_type::RANGE range) const;
|
||||
|
||||
private:
|
||||
const config& cfg_;
|
||||
|
||||
|
@ -244,6 +258,18 @@ private:
|
|||
const std::vector<config*>& possibleTraits_;
|
||||
|
||||
unit_race::GENDER gender_;
|
||||
|
||||
struct defensive_animation
|
||||
{
|
||||
defensive_animation(const config& cfg);
|
||||
bool matches(bool hits, attack_type::RANGE range) const;
|
||||
|
||||
enum { HIT, MISS, HIT_OR_MISS } hits;
|
||||
enum { SHORT, LONG, SHORT_OR_LONG } range;
|
||||
unit_animation animation;
|
||||
};
|
||||
|
||||
std::vector<defensive_animation> defensive_animations_;
|
||||
};
|
||||
|
||||
struct game_data
|
||||
|
|
|
@ -34,7 +34,7 @@ textbox::textbox(display& d, int width, const std::string& text, bool editable)
|
|||
scrollbar_(d,this),
|
||||
uparrow_(d,"",gui::button::TYPE_PRESS,"uparrow-button"),
|
||||
downarrow_(d,"",gui::button::TYPE_PRESS,"downarrow-button"),
|
||||
scroll_bottom_(false), wrap_(false)
|
||||
scroll_bottom_(false), wrap_(false), line_height_(0), yscroll_(0)
|
||||
{
|
||||
static const SDL_Rect area = d.screen_area();
|
||||
const int height = font::draw_text(NULL,area,font_size,font::NORMAL_COLOUR,"ABCD",0,0).h;
|
||||
|
@ -102,22 +102,6 @@ void textbox::draw()
|
|||
|
||||
SDL_Rect src;
|
||||
|
||||
// Fills the selected area
|
||||
if(is_selection()) {
|
||||
int x = minimum<int>(char_pos_[selstart_], char_pos_[selend_]) - text_pos_ + loc.x;
|
||||
int w = abs(char_pos_[selstart_] - char_pos_[selend_]);
|
||||
|
||||
if(!((x > loc.x + loc.w) || ((x + w) < loc.x))) {
|
||||
src.x = maximum<int>(x, loc.x);
|
||||
src.y = loc.y;
|
||||
src.w = src.x + w > loc.x + loc.w ? loc.x + loc.w - src.x : w;
|
||||
src.h = loc.h;
|
||||
|
||||
Uint32 colour = SDL_MapRGB(disp().video().getSurface()->format, 160, 0, 0);
|
||||
fill_rect_alpha(src,colour,140,disp().video().getSurface());
|
||||
}
|
||||
}
|
||||
|
||||
if(text_image_ != NULL) {
|
||||
src.y = 0;
|
||||
src.w = minimum<size_t>(loc.w,text_image_->w);
|
||||
|
@ -173,6 +157,35 @@ void textbox::draw()
|
|||
|
||||
scroll_bottom_ = false;
|
||||
|
||||
// Fills the selected area
|
||||
if(is_selection()) {
|
||||
const int start = minimum<int>(selstart_,selend_);
|
||||
const int end = maximum<int>(selstart_,selend_);
|
||||
int startx = char_x_[start];
|
||||
int starty = char_y_[start];
|
||||
const int endx = char_x_[end];
|
||||
const int endy = char_y_[end];
|
||||
|
||||
while(starty <= endy) {
|
||||
const size_t right = starty == endy ? endx : text_image_->w;
|
||||
if(right <= size_t(startx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Rect rect = {location().x + startx,location().y + starty - src.y,right - startx,line_height_};
|
||||
|
||||
SDL_Rect clip = location();
|
||||
const clip_rect_setter clipper(disp().video().getSurface(),clip);
|
||||
|
||||
Uint32 colour = SDL_MapRGB(disp().video().getSurface()->format, 160, 0, 0);
|
||||
fill_rect_alpha(rect,colour,140,disp().video().getSurface());
|
||||
|
||||
starty += int(line_height_);
|
||||
startx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
yscroll_ = src.y;
|
||||
SDL_BlitSurface(text_image_,&src,disp().video().getSurface(),&dest);
|
||||
}
|
||||
|
||||
|
@ -246,8 +259,10 @@ void textbox::scroll(int pos)
|
|||
void textbox::update_text_cache(bool changed)
|
||||
{
|
||||
if(changed) {
|
||||
char_pos_.clear();
|
||||
char_pos_.push_back(0);
|
||||
char_x_.clear();
|
||||
char_y_.clear();
|
||||
char_x_.push_back(0);
|
||||
char_y_.push_back(0);
|
||||
|
||||
// Re-calculate the position of each glyph. We approximate this by asking the
|
||||
// width of each substring, but this is a flawed assumption which won't work with
|
||||
|
@ -278,17 +293,20 @@ void textbox::update_text_cache(bool changed)
|
|||
int backup = itor - backup_itor;
|
||||
itor = backup_itor + 1;
|
||||
if(backup > 0) {
|
||||
char_pos_.erase(char_pos_.end()-backup, char_pos_.end());
|
||||
char_x_.erase(char_x_.end()-backup, char_x_.end());
|
||||
char_y_.erase(char_y_.end()-backup, char_y_.end());
|
||||
wrapped_text.erase(wrapped_text.end()-backup, wrapped_text.end());
|
||||
}
|
||||
}
|
||||
backup_itor = text_.end();
|
||||
wrapped_text.push_back(wchar_t('\n'));
|
||||
char_pos_.push_back(0);
|
||||
char_x_.push_back(0);
|
||||
char_y_.push_back(char_y_.back()+1);
|
||||
visible_string = "";
|
||||
} else {
|
||||
wrapped_text.push_back(*itor);
|
||||
char_pos_.push_back(w);
|
||||
char_x_.push_back(w);
|
||||
char_y_.push_back(char_y_.back() + (char(*itor) == '\n' ? 1 : 0));
|
||||
++itor;
|
||||
}
|
||||
}
|
||||
|
@ -300,9 +318,16 @@ void textbox::update_text_cache(bool changed)
|
|||
text_size_.h = location().h;
|
||||
|
||||
text_image_.assign(font::get_rendered_text(s, font_size, font::NORMAL_COLOUR));
|
||||
|
||||
//so far we've set char_y_ in terms of the line it's on, now set it in terms of proper y
|
||||
//co-ordinates, by calculating the height of a line, and multiplying each member of char_y_ by that height
|
||||
line_height_ = font::get_max_height(font_size);
|
||||
for(std::vector<int>::iterator i = char_y_.begin(); i != char_y_.end(); ++i) {
|
||||
*i = *i * line_height_;
|
||||
}
|
||||
}
|
||||
|
||||
int cursor_x = char_pos_[cursor_];
|
||||
int cursor_x = char_x_[cursor_];
|
||||
|
||||
if(cursor_x - text_pos_ > location().w) {
|
||||
text_pos_ = cursor_x - location().w;
|
||||
|
@ -338,31 +363,9 @@ void textbox::handle_event(const SDL_Event& event)
|
|||
const size_t beg = minimum<size_t>(size_t(selstart_),size_t(selend_));
|
||||
const size_t end = maximum<size_t>(size_t(selstart_),size_t(selend_));
|
||||
|
||||
std::string selection(end - beg,'x');
|
||||
std::copy(text_.begin()+beg,text_.begin()+end,selection.begin());
|
||||
copy_to_clipboard(selection);
|
||||
return;
|
||||
}
|
||||
|
||||
//if the user presses ctrl+v to paste text into the textbox
|
||||
if(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_v && (event.key.keysym.mod&KMOD_CTRL) != 0 && editable() && focus()) {
|
||||
const size_t beg = minimum<size_t>(size_t(selstart_),size_t(selend_));
|
||||
const size_t end = maximum<size_t>(size_t(selstart_),size_t(selend_));
|
||||
if(beg < text_.size() && end <= text_.size() && beg != end) {
|
||||
text_.erase(text_.begin()+beg,text_.begin()+end);
|
||||
selstart_ = selend_ = cursor_ = int(beg);
|
||||
}
|
||||
|
||||
const std::string& str = copy_from_clipboard();
|
||||
wide_string tmp;
|
||||
tmp.resize(str.size());
|
||||
std::copy(str.begin(),str.end(),tmp.begin());
|
||||
text_.insert(text_.begin()+minimum(size_t(cursor_),text_.size()),tmp.begin(),tmp.end());
|
||||
cursor_ += str.size();
|
||||
|
||||
update_text_cache(true);
|
||||
set_dirty();
|
||||
|
||||
wide_string ws = wide_string(text_.begin() + beg, text_.begin() + end);
|
||||
std::string s = wstring_to_string(ws);
|
||||
copy_to_clipboard(s);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -374,7 +377,7 @@ void textbox::handle_event(const SDL_Event& event)
|
|||
|
||||
if( (grabmouse_ && (event.type == SDL_MOUSEMOTION)) || (
|
||||
event.type == SDL_MOUSEBUTTONDOWN && (mousebuttons & SDL_BUTTON(1)) && !
|
||||
(mousex < location().x || mousex > location().x + location().w ||
|
||||
(mousex < location().x || mousex > location().x + location().w - (show_scrollbar() ? scrollbar_.get_max_width() : 0) ||
|
||||
mousey < location().y || mousey > location().y + location().h))) {
|
||||
|
||||
const int x = mousex - location().x + text_pos_;
|
||||
|
@ -382,12 +385,16 @@ void textbox::handle_event(const SDL_Event& event)
|
|||
int pos = 0;
|
||||
int distance = x;
|
||||
|
||||
for(int i = 1; i < char_pos_.size(); ++i) {
|
||||
for(int i = 1; i < int(char_x_.size()); ++i) {
|
||||
if(yscroll_ + y < char_y_[i]) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check individually each distance (if, one day, we support
|
||||
// RTL languages, char_pos[c] may not be monotonous.)
|
||||
if(abs(x - char_pos_[i]) < distance) {
|
||||
// RTL languages, char_x_[c] may not be monotonous.)
|
||||
if(abs(x - char_x_[i]) < distance && yscroll_ + y < char_y_[i] + line_height_) {
|
||||
pos = i;
|
||||
distance = abs(x - char_pos_[i]);
|
||||
distance = abs(x - char_x_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,13 +492,26 @@ void textbox::handle_event(const SDL_Event& event)
|
|||
if(character != 0)
|
||||
std::cerr << "Char: " << character << ", c = " << c << "\n";
|
||||
|
||||
if(character >= 32 && character != 127) {
|
||||
changed = true;
|
||||
if(is_selection())
|
||||
erase_selection();
|
||||
if(event.key.keysym.mod & KMOD_CTRL) {
|
||||
if(c == SDLK_v) {
|
||||
changed = true;
|
||||
if(is_selection())
|
||||
erase_selection();
|
||||
|
||||
text_.insert(text_.begin()+cursor_,character);
|
||||
++cursor_;
|
||||
wide_string s = string_to_wstring(copy_from_clipboard());
|
||||
|
||||
text_.insert(text_.begin()+cursor_, s.begin(), s.end());
|
||||
cursor_ += s.size();
|
||||
}
|
||||
} else {
|
||||
if(character >= 32 && character != 127) {
|
||||
changed = true;
|
||||
if(is_selection())
|
||||
erase_selection();
|
||||
|
||||
text_.insert(text_.begin()+cursor_,character);
|
||||
++cursor_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
int text_pos_;
|
||||
int cursor_pos_;
|
||||
std::vector<int> char_pos_;
|
||||
std::vector<int> char_x_, char_y_;
|
||||
|
||||
bool editable_;
|
||||
|
||||
|
@ -80,6 +80,8 @@ private:
|
|||
|
||||
bool wrap_;
|
||||
|
||||
size_t line_height_, yscroll_;
|
||||
|
||||
void handle_event(const SDL_Event& event);
|
||||
|
||||
void draw_cursor(int pos, display &disp) const;
|
||||
|
|
|
@ -8,19 +8,19 @@ namespace {
|
|||
namespace gui {
|
||||
|
||||
widget::widget(const widget &o) :
|
||||
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), hidden_(false), volatile_(o.volatile_),
|
||||
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), needs_restore_(o.needs_restore_), hidden_(false), volatile_(o.volatile_),
|
||||
help_string_(o.help_string_), help_text_(o.help_text_)
|
||||
{
|
||||
bg_backup();
|
||||
}
|
||||
|
||||
widget::widget(display& disp) :
|
||||
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false), help_string_(0)
|
||||
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), needs_restore_(false), hidden_(false), volatile_(false), help_string_(0)
|
||||
{
|
||||
}
|
||||
|
||||
widget::widget(display& disp, const SDL_Rect& rect) :
|
||||
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false), help_string_(0)
|
||||
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), needs_restore_(false), hidden_(false), volatile_(false), help_string_(0)
|
||||
{
|
||||
set_location(rect);
|
||||
bg_backup();
|
||||
|
@ -132,6 +132,9 @@ void widget::set_dirty(bool dirty)
|
|||
}
|
||||
|
||||
dirty_ = dirty;
|
||||
if(dirty_ == false) {
|
||||
needs_restore_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
const bool widget::dirty() const
|
||||
|
@ -146,7 +149,14 @@ void widget::bg_backup()
|
|||
|
||||
void widget::bg_restore() const
|
||||
{
|
||||
restorer_.restore();
|
||||
if(needs_restore_) {
|
||||
restorer_.restore();
|
||||
needs_restore_ = false;
|
||||
} else {
|
||||
//this function should be able to be relied upon to update the rectangle,
|
||||
//so do that even if we don't restore
|
||||
update_rect(location());
|
||||
}
|
||||
}
|
||||
|
||||
void widget::handle_event(const SDL_Event& event)
|
||||
|
|
|
@ -69,6 +69,7 @@ private:
|
|||
SDL_Rect rect_;
|
||||
bool focus_; // Should user input be ignored?
|
||||
bool dirty_; // Does the widget need drawn?
|
||||
mutable bool needs_restore_; //have we drawn ourselves, so that if moved, we need to restore the background?
|
||||
|
||||
bool hidden_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue