set svn:eol style native on all appropriate text files missing it...
...and correcting the line endings if necessary
This commit is contained in:
parent
f7d654808e
commit
d751f29884
8 changed files with 1209 additions and 1209 deletions
|
@ -1,16 +1,16 @@
|
|||
THE GREEN ISLE
|
||||
|
||||
BLACKMORE
|
||||
X:635 Y:282
|
||||
|
||||
CLEARWATER
|
||||
X:566 Y:388
|
||||
|
||||
JEVYAN
|
||||
X:400 Y:190
|
||||
|
||||
SOUTHBAY
|
||||
X:364 Y:459
|
||||
|
||||
STORMVALE
|
||||
THE GREEN ISLE
|
||||
|
||||
BLACKMORE
|
||||
X:635 Y:282
|
||||
|
||||
CLEARWATER
|
||||
X:566 Y:388
|
||||
|
||||
JEVYAN
|
||||
X:400 Y:190
|
||||
|
||||
SOUTHBAY
|
||||
X:364 Y:459
|
||||
|
||||
STORMVALE
|
||||
X:312 Y:314
|
|
@ -1,179 +1,179 @@
|
|||
#textdomain wesnoth-trow
|
||||
[unit]
|
||||
id=Wesfolk Lady
|
||||
name= _ "female^Wesfolk Lady"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/outlaw+female.png"
|
||||
{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=46
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_2}
|
||||
{ABILITY_DISTRACT (Wesfolk Lady)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=80
|
||||
level=2
|
||||
alignment=chaotic
|
||||
advanceto=Wesfolk Leader
|
||||
cost=36
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which continues increasing with time, as does her natural leadership.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/outlaw+female-defend.png" "units/human-outlaws/outlaw+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description=_"staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=8
|
||||
number=2
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description=_"sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=6
|
||||
number=3
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-attack1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-attack1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-attack2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-melee-1.png"
|
||||
[/frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-melee-2.png"
|
||||
sound=mace.wav
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-melee-2.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/outlaw+female-melee-3.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[idle_anim]
|
||||
{STANDARD_IDLE_FILTER}
|
||||
[frame]
|
||||
begin=0
|
||||
end=100
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=100
|
||||
end=200
|
||||
image="units/human-outlaws/outlaw-idle-7.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=200
|
||||
end=300
|
||||
image="units/human-outlaws/outlaw-idle-5.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=300
|
||||
end=400
|
||||
image="units/human-outlaws/outlaw-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=400
|
||||
end=500
|
||||
image="units/human-outlaws/outlaw-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=500
|
||||
end=600
|
||||
image="units/human-outlaws/outlaw-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=600
|
||||
end=700
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=700
|
||||
end=800
|
||||
image="units/human-outlaws/outlaw-idle-6.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=800
|
||||
end=900
|
||||
image="units/human-outlaws/outlaw-idle-5.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=900
|
||||
end=1400
|
||||
image="units/human-outlaws/outlaw-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1400
|
||||
end=1500
|
||||
image="units/human-outlaws/outlaw-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1500
|
||||
end=1600
|
||||
image="units/human-outlaws/outlaw-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1600
|
||||
end=1700
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[/idle_anim]
|
||||
[/unit]
|
||||
#textdomain wesnoth-trow
|
||||
[unit]
|
||||
id=Wesfolk Lady
|
||||
name= _ "female^Wesfolk Lady"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/outlaw+female.png"
|
||||
{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=46
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_2}
|
||||
{ABILITY_DISTRACT (Wesfolk Lady)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=80
|
||||
level=2
|
||||
alignment=chaotic
|
||||
advanceto=Wesfolk Leader
|
||||
cost=36
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which continues increasing with time, as does her natural leadership.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/outlaw+female-defend.png" "units/human-outlaws/outlaw+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description=_"staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=8
|
||||
number=2
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description=_"sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=6
|
||||
number=3
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-attack1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-attack1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-attack2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/outlaw+female-melee-1.png"
|
||||
[/frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-melee-2.png"
|
||||
sound=mace.wav
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/outlaw+female-melee-2.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/outlaw+female-melee-3.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[idle_anim]
|
||||
{STANDARD_IDLE_FILTER}
|
||||
[frame]
|
||||
begin=0
|
||||
end=100
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=100
|
||||
end=200
|
||||
image="units/human-outlaws/outlaw-idle-7.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=200
|
||||
end=300
|
||||
image="units/human-outlaws/outlaw-idle-5.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=300
|
||||
end=400
|
||||
image="units/human-outlaws/outlaw-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=400
|
||||
end=500
|
||||
image="units/human-outlaws/outlaw-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=500
|
||||
end=600
|
||||
image="units/human-outlaws/outlaw-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=600
|
||||
end=700
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=700
|
||||
end=800
|
||||
image="units/human-outlaws/outlaw-idle-6.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=800
|
||||
end=900
|
||||
image="units/human-outlaws/outlaw-idle-5.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=900
|
||||
end=1400
|
||||
image="units/human-outlaws/outlaw-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1400
|
||||
end=1500
|
||||
image="units/human-outlaws/outlaw-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1500
|
||||
end=1600
|
||||
image="units/human-outlaws/outlaw-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=1600
|
||||
end=1700
|
||||
image="units/human-outlaws/outlaw-idle-1.png"
|
||||
[/frame]
|
||||
[/idle_anim]
|
||||
[/unit]
|
||||
|
|
|
@ -1,138 +1,138 @@
|
|||
#textdomain wesnoth-trow
|
||||
|
||||
[unit]
|
||||
id=Wesfolk Leader
|
||||
name= _ "Wesfolk Leader"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
#{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=62
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_3}
|
||||
{ABILITY_DISTRACT (Wesfolk Leader)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=100
|
||||
level=3
|
||||
alignment=chaotic
|
||||
advanceto=null
|
||||
{AMLA_TOUGH 3}
|
||||
cost=60
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which continues increasing with time, as does her natural leadership.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/fugitive+female-defend.png" "units/human-outlaws/fugitive+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description= _ "staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=12
|
||||
number=2
|
||||
icon=attacks/mace.png
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description= _ "sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=8
|
||||
number=4
|
||||
icon=attacks/sling.png
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
hits=yes
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female-ranged-1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-ranged-2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
hits=no
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female-ranged-1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-ranged-2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-melee-1.png"
|
||||
sound=mace.wav
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-melee-1.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[/unit]
|
||||
#textdomain wesnoth-trow
|
||||
|
||||
[unit]
|
||||
id=Wesfolk Leader
|
||||
name= _ "Wesfolk Leader"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
#{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=62
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_3}
|
||||
{ABILITY_DISTRACT (Wesfolk Leader)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=100
|
||||
level=3
|
||||
alignment=chaotic
|
||||
advanceto=null
|
||||
{AMLA_TOUGH 3}
|
||||
cost=60
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which continues increasing with time, as does her natural leadership.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/fugitive+female-defend.png" "units/human-outlaws/fugitive+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description= _ "staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=12
|
||||
number=2
|
||||
icon=attacks/mace.png
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description= _ "sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=8
|
||||
number=4
|
||||
icon=attacks/sling.png
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
hits=yes
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female-ranged-1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-ranged-2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
hits=no
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female-ranged-1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-ranged-2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-melee-1.png"
|
||||
sound=mace.wav
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=mace
|
||||
[/attack_filter]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/fugitive+female-melee-1.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=50
|
||||
end=150
|
||||
image="units/human-outlaws/fugitive+female.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[/unit]
|
||||
|
|
|
@ -1,159 +1,159 @@
|
|||
#textdomain wesnoth-trow
|
||||
[unit]
|
||||
id=Wesfolk Outcast
|
||||
name= _ "female^Wesfolk Outcast"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/footpad+female.png"
|
||||
ellipse="misc/ellipse"
|
||||
{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=33
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_1}
|
||||
{ABILITY_DISTRACT (Wesfolk Outcast)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=40
|
||||
level=1
|
||||
alignment=chaotic
|
||||
advanceto=Wesfolk Lady
|
||||
cost=18
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which she can lend to her people for turning a fight in their favour.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/footpad+female-defend.png" "units/human-outlaws/footpad+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description=_"staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=5
|
||||
number=2
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description=_"sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=4
|
||||
number=3
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-attack1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-attack1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/footpad+female-attack2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=club
|
||||
[/attack_filter]
|
||||
[frame]
|
||||
begin=-250
|
||||
end=-200
|
||||
image="units/human-outlaws/footpad+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-melee-1.png"
|
||||
[/frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-100
|
||||
end=100
|
||||
image="units/human-outlaws/footpad+female-melee-2.png"
|
||||
sound=staff.wav
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-100
|
||||
end=100
|
||||
image="units/human-outlaws/footpad+female-melee-2.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=100
|
||||
end=200
|
||||
image="units/human-outlaws/footpad+female-melee-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=200
|
||||
end=300
|
||||
image="units/human-outlaws/footpad+female-melee-4.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[idle_anim]
|
||||
{STANDARD_IDLE_FILTER}
|
||||
start_time=0
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-1.png"
|
||||
[/frame]
|
||||
[/idle_anim]
|
||||
[/unit]
|
||||
#textdomain wesnoth-trow
|
||||
[unit]
|
||||
id=Wesfolk Outcast
|
||||
name= _ "female^Wesfolk Outcast"
|
||||
race=human
|
||||
gender=female
|
||||
image="units/human-outlaws/footpad+female.png"
|
||||
ellipse="misc/ellipse"
|
||||
{MAGENTA_IS_THE_TEAM_COLOR}
|
||||
hitpoints=33
|
||||
[abilities]
|
||||
{ABILITY_LEADERSHIP_LEVEL_1}
|
||||
{ABILITY_DISTRACT (Wesfolk Outcast)}
|
||||
[/abilities]
|
||||
movement_type=elusivefoot
|
||||
movement=7
|
||||
experience=40
|
||||
level=1
|
||||
alignment=chaotic
|
||||
advanceto=Wesfolk Lady
|
||||
cost=18
|
||||
usage=mixed fighter
|
||||
unit_description= _ "Born in the Wesfolk aristocracy, she and her people were excluded from society by their lords, who betrayed their loyalty when a war against Haldric's people was being lost. This outcast still converves her nobleness in her veins, and in the battle-field she has earned valuable experience, which she can lend to her people for turning a fight in their favour.
|
||||
|
||||
Special Notes:"+{SPECIAL_NOTES_DISTRACT}+{SPECIAL_NOTES_LEADERSHIP}
|
||||
die_sound={SOUND_LIST:HUMAN_FEMALE_DIE}
|
||||
{DEFENSE_ANIM "units/human-outlaws/footpad+female-defend.png" "units/human-outlaws/footpad+female.png" {SOUND_LIST:HUMAN_FEMALE_HIT} }
|
||||
[attack]
|
||||
name=staff
|
||||
description=_"staff"
|
||||
icon=attacks/quarterstaff.png
|
||||
type=impact
|
||||
range=melee
|
||||
damage=5
|
||||
number=2
|
||||
[/attack]
|
||||
[attack]
|
||||
name=sling
|
||||
description=_"sling"
|
||||
type=impact
|
||||
range=ranged
|
||||
damage=4
|
||||
number=3
|
||||
[/attack]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=sling
|
||||
[/attack_filter]
|
||||
[missile_frame]
|
||||
begin=-150
|
||||
end=0
|
||||
image="projectiles/stone.png"
|
||||
image_diagonal="projectiles/stone.png"
|
||||
[/missile_frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-attack1.png"
|
||||
sound=sling.ogg
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-400
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-attack1.png"
|
||||
sound=sling-miss.ogg
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=-100
|
||||
end=50
|
||||
image="units/human-outlaws/footpad+female-attack2.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[attack_anim]
|
||||
[attack_filter]
|
||||
name=club
|
||||
[/attack_filter]
|
||||
[frame]
|
||||
begin=-250
|
||||
end=-200
|
||||
image="units/human-outlaws/footpad+female.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=-200
|
||||
end=-100
|
||||
image="units/human-outlaws/footpad+female-melee-1.png"
|
||||
[/frame]
|
||||
[if]
|
||||
hits=yes
|
||||
[frame]
|
||||
begin=-100
|
||||
end=100
|
||||
image="units/human-outlaws/footpad+female-melee-2.png"
|
||||
sound=staff.wav
|
||||
[/frame]
|
||||
[/if]
|
||||
[else]
|
||||
hits=no
|
||||
[frame]
|
||||
begin=-100
|
||||
end=100
|
||||
image="units/human-outlaws/footpad+female-melee-2.png"
|
||||
sound={SOUND_LIST:MISS}
|
||||
[/frame]
|
||||
[/else]
|
||||
[frame]
|
||||
begin=100
|
||||
end=200
|
||||
image="units/human-outlaws/footpad+female-melee-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
begin=200
|
||||
end=300
|
||||
image="units/human-outlaws/footpad+female-melee-4.png"
|
||||
[/frame]
|
||||
[/attack_anim]
|
||||
[idle_anim]
|
||||
{STANDARD_IDLE_FILTER}
|
||||
start_time=0
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-1.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-4.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-3.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-2.png"
|
||||
[/frame]
|
||||
[frame]
|
||||
image="units/human-outlaws/footpad+female-idle-1.png"
|
||||
[/frame]
|
||||
[/idle_anim]
|
||||
[/unit]
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
#textdomain wesnoth-trow
|
||||
|
||||
#define ABILITY_DISTRACT SELFTYPE
|
||||
[skirmisher]
|
||||
id=distract
|
||||
name= _ "distract"
|
||||
description= _ "Distract:
|
||||
This unit negates enemy Zones of Control around itself for friendly units (but not for itself)."
|
||||
[filter]
|
||||
[not]
|
||||
type={SELFTYPE}
|
||||
[/not]
|
||||
[/filter]
|
||||
[affect_adjacent]
|
||||
adjacent=n,ne,se,s,sw,nw
|
||||
[filter]
|
||||
[not]
|
||||
type={SELFTYPE}
|
||||
[/not]
|
||||
[/filter]
|
||||
[/affect_adjacent]
|
||||
[/skirmisher]
|
||||
#enddef
|
||||
|
||||
#define SPECIAL_NOTES_DISTRACT
|
||||
_"This unit is capable of distracting oponents, allowing friendly unis to trespass their Zones of Control and move unhindered around them."#enddef
|
||||
#textdomain wesnoth-trow
|
||||
|
||||
#define ABILITY_DISTRACT SELFTYPE
|
||||
[skirmisher]
|
||||
id=distract
|
||||
name= _ "distract"
|
||||
description= _ "Distract:
|
||||
This unit negates enemy Zones of Control around itself for friendly units (but not for itself)."
|
||||
[filter]
|
||||
[not]
|
||||
type={SELFTYPE}
|
||||
[/not]
|
||||
[/filter]
|
||||
[affect_adjacent]
|
||||
adjacent=n,ne,se,s,sw,nw
|
||||
[filter]
|
||||
[not]
|
||||
type={SELFTYPE}
|
||||
[/not]
|
||||
[/filter]
|
||||
[/affect_adjacent]
|
||||
[/skirmisher]
|
||||
#enddef
|
||||
|
||||
#define SPECIAL_NOTES_DISTRACT
|
||||
_"This unit is capable of distracting oponents, allowing friendly unis to trespass their Zones of Control and move unhindered around them."#enddef
|
||||
|
|
|
@ -1,61 +1,61 @@
|
|||
"""
|
||||
randomtraits.py -- Python routine for upconverting v1.3-1.3.7 saved replays
|
||||
to v1.3.8+ format. Backups are saved to /backup
|
||||
Author: Sapient (Patrick Parker), 2007
|
||||
"""
|
||||
from wesnoth.wmliterator import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""Perform a random_traits=no conversion on a saved replay"""
|
||||
import os, glob, re
|
||||
versionPattern = re.compile(r'\s*version="1.3.([0-9]+).*')
|
||||
didSomething = False
|
||||
print 'Current directory is', os.getcwd()
|
||||
flist = glob.glob(os.path.join(os.getcwd(), raw_input('What is the path to the saved replay?\n')))
|
||||
while flist:
|
||||
fname = flist.pop()
|
||||
if os.path.isdir(fname):
|
||||
flist += glob.glob(fname + os.path.sep + '*')
|
||||
continue
|
||||
if not os.path.isfile(fname) or os.path.splitext(fname)[1]:
|
||||
continue
|
||||
print 'Reading', fname+'...'
|
||||
f = open(fname, 'U')
|
||||
itor = wmlfind('version=', WmlIterator(f.readlines()))
|
||||
if itor is None:
|
||||
f.close()
|
||||
continue
|
||||
didSomething = True
|
||||
changed = 0
|
||||
elems = set()
|
||||
match = versionPattern.match(itor.text)
|
||||
if (match is not None and int(match.group(1)) < 8)\
|
||||
or ('"test"' in itor.text and 'yes'.startswith(raw_input('Warning: %s\n\tversion is "test", convert? '%fname).lower())):
|
||||
itor.reset()
|
||||
i = wmlfind('[unit]', itor)
|
||||
while i is not None:
|
||||
elems.add(i.lineno)
|
||||
i = wmlfind('[unit]', i)
|
||||
i = wmlfindin('random_traits=', '[unit]', itor)
|
||||
while i is not None:
|
||||
elems.remove(i.scopes[-1].lineno)
|
||||
i = wmlfindin('random_traits=', '[unit]', i)
|
||||
for elem in sorted(elems):
|
||||
changed += 1
|
||||
itor.lines = itor.lines[:elem+changed] + ['random_traits="no"\n'] + itor.lines[elem+changed:]
|
||||
f.close()
|
||||
if changed:
|
||||
backup = os.path.join(os.path.dirname(fname), 'backup', os.path.basename(fname))
|
||||
print 'Creating backup', backup
|
||||
os.renames(fname, backup)
|
||||
f = open(fname, "w")
|
||||
f.write("".join(itor.lines))
|
||||
f.close()
|
||||
print 'Converted', fname
|
||||
print '\t(%d line(s) changed)'%changed
|
||||
if not didSomething:
|
||||
print 'That is not a valid v1.3-v1.3.7 replay savefile'
|
||||
if os.name == 'nt' and os.path.splitext(__file__)[0].endswith('randomtraits') and not sys.argv[1:]:
|
||||
os.system('pause')
|
||||
|
||||
# randomtraits.py ends here
|
||||
"""
|
||||
randomtraits.py -- Python routine for upconverting v1.3-1.3.7 saved replays
|
||||
to v1.3.8+ format. Backups are saved to /backup
|
||||
Author: Sapient (Patrick Parker), 2007
|
||||
"""
|
||||
from wesnoth.wmliterator import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""Perform a random_traits=no conversion on a saved replay"""
|
||||
import os, glob, re
|
||||
versionPattern = re.compile(r'\s*version="1.3.([0-9]+).*')
|
||||
didSomething = False
|
||||
print 'Current directory is', os.getcwd()
|
||||
flist = glob.glob(os.path.join(os.getcwd(), raw_input('What is the path to the saved replay?\n')))
|
||||
while flist:
|
||||
fname = flist.pop()
|
||||
if os.path.isdir(fname):
|
||||
flist += glob.glob(fname + os.path.sep + '*')
|
||||
continue
|
||||
if not os.path.isfile(fname) or os.path.splitext(fname)[1]:
|
||||
continue
|
||||
print 'Reading', fname+'...'
|
||||
f = open(fname, 'U')
|
||||
itor = wmlfind('version=', WmlIterator(f.readlines()))
|
||||
if itor is None:
|
||||
f.close()
|
||||
continue
|
||||
didSomething = True
|
||||
changed = 0
|
||||
elems = set()
|
||||
match = versionPattern.match(itor.text)
|
||||
if (match is not None and int(match.group(1)) < 8)\
|
||||
or ('"test"' in itor.text and 'yes'.startswith(raw_input('Warning: %s\n\tversion is "test", convert? '%fname).lower())):
|
||||
itor.reset()
|
||||
i = wmlfind('[unit]', itor)
|
||||
while i is not None:
|
||||
elems.add(i.lineno)
|
||||
i = wmlfind('[unit]', i)
|
||||
i = wmlfindin('random_traits=', '[unit]', itor)
|
||||
while i is not None:
|
||||
elems.remove(i.scopes[-1].lineno)
|
||||
i = wmlfindin('random_traits=', '[unit]', i)
|
||||
for elem in sorted(elems):
|
||||
changed += 1
|
||||
itor.lines = itor.lines[:elem+changed] + ['random_traits="no"\n'] + itor.lines[elem+changed:]
|
||||
f.close()
|
||||
if changed:
|
||||
backup = os.path.join(os.path.dirname(fname), 'backup', os.path.basename(fname))
|
||||
print 'Creating backup', backup
|
||||
os.renames(fname, backup)
|
||||
f = open(fname, "w")
|
||||
f.write("".join(itor.lines))
|
||||
f.close()
|
||||
print 'Converted', fname
|
||||
print '\t(%d line(s) changed)'%changed
|
||||
if not didSomething:
|
||||
print 'That is not a valid v1.3-v1.3.7 replay savefile'
|
||||
if os.name == 'nt' and os.path.splitext(__file__)[0].endswith('randomtraits') and not sys.argv[1:]:
|
||||
os.system('pause')
|
||||
|
||||
# randomtraits.py ends here
|
||||
|
|
|
@ -1,360 +1,360 @@
|
|||
"""
|
||||
wmliterator.py -- Python routines for navigating a Battle For Wesnoth WML tree
|
||||
Author: Sapient (Patrick Parker), 2007
|
||||
"""
|
||||
import sys, re, copy
|
||||
keyPattern = re.compile('(\w+)(,\s?\w+)*\s*=')
|
||||
keySplit = re.compile(r'[=,\s]')
|
||||
tagPattern = re.compile(r'(^|(?<![\w\|\}]))(\[.*?\])')
|
||||
macroOpenPattern = re.compile(r'(\{[^\s\}]*)')
|
||||
macroClosePattern = re.compile(r'\}')
|
||||
|
||||
silenceErrors = {}
|
||||
|
||||
def wmlfind(element, wmlItor):
|
||||
"""Find a simple element from traversing a WML iterator"""
|
||||
for itor in wmlItor.copy():
|
||||
if element == itor.element:
|
||||
return itor
|
||||
return None
|
||||
|
||||
def wmlfindin(element, scopeElement, wmlItor):
|
||||
"""Find an element inside a particular type of scope element"""
|
||||
for itor in wmlItor.copy():
|
||||
if element == itor.element:
|
||||
if itor.scopes:
|
||||
if scopeElement == itor.scopes[-1].element:
|
||||
return itor
|
||||
elif not scopeElement:
|
||||
# allow searching in the empty scope
|
||||
return itor
|
||||
return None
|
||||
|
||||
def parseQuotes(lines, fname, lineno):
|
||||
"""Return the line or multiline text if a quote spans multiple lines"""
|
||||
text = lines[lineno]
|
||||
span = 1
|
||||
begincomment = text.find('#')
|
||||
if begincomment < 0:
|
||||
begincomment = None
|
||||
beginquote = text[:begincomment].find('"')
|
||||
while beginquote >= 0:
|
||||
endquote = -1
|
||||
beginofend = beginquote+1
|
||||
while endquote < 0:
|
||||
endquote = text.find('"', beginofend)
|
||||
if endquote < 0:
|
||||
if lineno + span >= len(lines):
|
||||
printError(fname, 'reached EOF due to unterminated string at line', lineno+1)
|
||||
return text, span
|
||||
text += lines[lineno + span]
|
||||
span += 1
|
||||
beginofend = text.rfind('\n', beginofend, len(text)-1)
|
||||
begincomment = text.find('#', endquote+1)
|
||||
if begincomment < 0:
|
||||
begincomment = None
|
||||
beginquote = text[:begincomment].find('"', endquote+1)
|
||||
return text, span
|
||||
|
||||
def isDirective(elem):
|
||||
"Identify things that shouldn't be indented."
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
for prefix in ("#ifdef", "#else", "#endif", "#define", "#enddef"):
|
||||
if elem.startswith(prefix):
|
||||
return True
|
||||
return False
|
||||
|
||||
def isCloser(elem):
|
||||
"Are we looking at a closing tag?"
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
return elem.startswith("[/")
|
||||
|
||||
def isOpener(elem):
|
||||
"Are we looking at an opening tag?"
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
return elem.startswith("[") and not isCloser(elem)
|
||||
|
||||
def closeScope(scopes, closerElement, fname, lineno):
|
||||
"""Close the most recently opened scope. Return false if not enough scopes.
|
||||
note: directives close all the way back to the last open directive
|
||||
non-directives cannot close a directive and will no-op in that case."""
|
||||
try:
|
||||
if isDirective(closerElement):
|
||||
while not isDirective(scopes.pop()):
|
||||
pass
|
||||
elif not isDirective(scopes[-1]):
|
||||
closed = scopes.pop()
|
||||
elem = closed
|
||||
if isinstance(closed, WmlIterator):
|
||||
elem = closed.element
|
||||
if ((isOpener(elem) and closerElement != '[/'+elem[1:]
|
||||
and '+'+closerElement != elem[1]+'[/'+elem[2:])
|
||||
or (elem.startswith('{') and closerElement.find('macro')<0)):
|
||||
printError(fname, 'reached', closerElement, 'at line', lineno+1, 'before closing scope', elem, '(%d)'%lineno)
|
||||
scopes.append(closed) # to reduce additional errors (hopefully)
|
||||
return True
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
def printError(fname, *misc):
|
||||
"""Print error associated with a given file; avoid printing duplicates"""
|
||||
if fname:
|
||||
silenceValue = ' '.join(map(str, misc))
|
||||
if fname not in silenceErrors:
|
||||
print >>sys.stderr, fname
|
||||
silenceErrors[fname] = set()
|
||||
elif silenceValue in silenceErrors[fname]:
|
||||
return # do not print a duplicate error for this file
|
||||
silenceErrors[fname].add(silenceValue)
|
||||
print >>sys.stderr, 'wmliterator:',
|
||||
for item in misc:
|
||||
print >>sys.stderr, item,
|
||||
print >>sys.stderr #terminate line
|
||||
|
||||
def printScopeError(elementType, fname, lineno):
|
||||
"""Print out warning if a scope was unable to close"""
|
||||
printError(fname, 'attempt to close empty scope at', elementType, 'line', lineno+1)
|
||||
|
||||
def parseElements(text, fname, lineno, scopes):
|
||||
"""Remove any closed scopes, return a list of element names
|
||||
and list of new unclosed scopes
|
||||
Element Types:
|
||||
tags: one of "[tag_name]" or "[/tag_name]"
|
||||
[tag_name] - opens a scope
|
||||
[/tag_name] - closes a scope
|
||||
keys: either "key=" or ("key1=", "key2=") for multi-assignment
|
||||
key= - does not affect the scope
|
||||
key1,key2= - multi-assignment returns multiple elements
|
||||
directives: one of "#ifdef", "#else", "#endif", "#define", "#enddef"
|
||||
#ifdef - opens a scope
|
||||
#else - closes a scope, also opens a new scope
|
||||
#endif - closes a scope
|
||||
#define - opens a scope
|
||||
#enddef - closes a scope
|
||||
macro calls: "{MACRO_NAME}"
|
||||
{MACRO_NAME - opens a scope
|
||||
} - closes a scope (not an element)
|
||||
"""
|
||||
closeMacroType = 'end of macro'
|
||||
elements = [] #(elementType, sortPos, scopeDelta)
|
||||
# first remove any quoted strings
|
||||
beginquote = text.find('"')
|
||||
while beginquote >= 0:
|
||||
endquote = text.find('"', beginquote+1)
|
||||
if endquote < 0:
|
||||
text = text[:beginquote]
|
||||
beginquote = -1 #terminate loop
|
||||
else:
|
||||
text = text[:beginquote] + text[endquote+1:]
|
||||
beginquote = text.find('"')
|
||||
# next remove any comments
|
||||
text = text.lstrip()
|
||||
commentSearch = 1
|
||||
if text.startswith('#ifdef'):
|
||||
return (['#ifdef'],)*2
|
||||
elif text.startswith('#else'):
|
||||
if not closeScope(scopes, '#else', fname, lineno):
|
||||
printScopeError('#else', fname, lineno)
|
||||
return (['#else'],)*2
|
||||
elif text.startswith('#endif'):
|
||||
if not closeScope(scopes, '#endif', fname, lineno):
|
||||
printScopeError('#endif', fname, lineno)
|
||||
return ['#endif'], []
|
||||
elif text.startswith('#define'):
|
||||
return (['#define'],)*2
|
||||
elif text.find('#enddef') >= 0:
|
||||
elements.append(('#enddef', text.find('#enddef'), -1))
|
||||
else:
|
||||
commentSearch = 0
|
||||
begincomment = text.find('#', commentSearch)
|
||||
if begincomment >= 0:
|
||||
text = text[:begincomment]
|
||||
#now find elements in a loop
|
||||
for m in tagPattern.finditer(text):
|
||||
delta = 1
|
||||
if isCloser(m.group(2)):
|
||||
delta = -1
|
||||
elements.append((m.group(2), m.start(), delta))
|
||||
for m in keyPattern.finditer(text):
|
||||
for i, k in enumerate(keySplit.split(m.group(0))):
|
||||
if k:
|
||||
elements.append((k+'=', m.start()+i, 0))
|
||||
for m in macroOpenPattern.finditer(text):
|
||||
elements.append((m.group(1)+'}', m.start(), 1))
|
||||
for m in macroClosePattern.finditer(text):
|
||||
elements.append((closeMacroType, m.start(), -1))
|
||||
#sort by start position
|
||||
elements.sort(key=lambda x:x[1])
|
||||
resultElements = []
|
||||
openedScopes = []
|
||||
for elem, sortPos, scopeDelta in elements:
|
||||
while scopeDelta < 0:
|
||||
if not(closeScope(openedScopes, elem, fname, lineno)\
|
||||
or closeScope(scopes, elem, fname, lineno)):
|
||||
printScopeError(elem, fname, lineno)
|
||||
scopeDelta += 1
|
||||
while scopeDelta > 0:
|
||||
openedScopes.append(elem)
|
||||
scopeDelta -= 1
|
||||
if elem != closeMacroType:
|
||||
resultElements.append(elem)
|
||||
return resultElements, openedScopes
|
||||
|
||||
class WmlIterator(object):
|
||||
"""Return an iterable WML navigation object.
|
||||
note: if changes are made to lines while iterating, this may produce
|
||||
unexpected results. In such case, seek() to the linenumber of a
|
||||
scope behind where changes were made.
|
||||
Important Attributes:
|
||||
lines - this is an internal list of all the physical lines
|
||||
scopes - this is an internal list of all open scopes (as iterators)
|
||||
note: when retreiving an iterator from this list, always
|
||||
use a copy to perform seek() or next(), and not the original
|
||||
element - the wml tag, key, or macro name for this logical line
|
||||
(in complex cases, this may be a tuple of elements...
|
||||
see parseElements for list of possible values)
|
||||
text - the exact text of this logical line, as it appears in the
|
||||
original source, and ending with a newline
|
||||
note: the logical line also includes multi-line quoted strings
|
||||
span - the number of physical lines in this logical line:
|
||||
always 1, unless text contains a multi-line quoted string
|
||||
lineno - a zero-based line index marking where this text begins
|
||||
"""
|
||||
def __init__(self, lines, fname=None, begin=-1, endScope=None):
|
||||
"Initialize a new WmlIterator"
|
||||
self.lines = lines
|
||||
self.fname = fname
|
||||
self.reset()
|
||||
self.seek(begin)
|
||||
|
||||
def __iter__(self):
|
||||
"""The magic iterator method"""
|
||||
return self
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Compare two iterators"""
|
||||
return cmp((self.fname, self.lineno, self.element),
|
||||
(other.fname, other.lineno, other.element))
|
||||
|
||||
def reset(self):
|
||||
"""Reset any line tracking information to defaults"""
|
||||
self.lineno = -1
|
||||
self.scopes = []
|
||||
self.nextScopes = []
|
||||
self.text = ""
|
||||
self.span = 1
|
||||
self.element = ""
|
||||
return self
|
||||
|
||||
def seek(self, lineno, clearEnd=True):
|
||||
"""Move the iterator to a specific line number"""
|
||||
if clearEnd:
|
||||
self.endScope = None
|
||||
if lineno < self.lineno:
|
||||
for scope in reversed(self.scopes):
|
||||
# if moving backwards, try to re-use a scope iterator
|
||||
if scope.lineno <= lineno:
|
||||
# copy the scope iterator's state to self
|
||||
self.__dict__ = dict(scope.__dict__)
|
||||
self.scopes = scope.scopes[:]
|
||||
self.nextScopes = scope.nextScopes[:]
|
||||
break
|
||||
else:
|
||||
# moving backwards past all scopes forces a reset
|
||||
self.reset()
|
||||
while self.lineno + self.span - 1 < lineno:
|
||||
self.next()
|
||||
return self
|
||||
|
||||
def hasNext(self):
|
||||
"""Some loops may wish to check this method instead of calling next()
|
||||
and handling StopIteration... note: inaccurate for ScopeIterators"""
|
||||
return len(self.lines) > self.lineno + self.span
|
||||
|
||||
def copy(self):
|
||||
"""Return a copy of this iterator"""
|
||||
itor = copy.copy(self)
|
||||
itor.scopes = self.scopes[:]
|
||||
itor.nextScopes = self.nextScopes[:]
|
||||
return itor
|
||||
|
||||
def __str__(self):
|
||||
"""Return a pretty string representation"""
|
||||
if self.lineno == -1:
|
||||
return 'beginning of file'
|
||||
loc = ' at line ' + str(self.lineno+1)
|
||||
if self.element:
|
||||
return str(self.element) + loc
|
||||
if self.text.strip():
|
||||
return 'text' + loc
|
||||
return 'whitespace' + loc
|
||||
|
||||
def __repr__(self):
|
||||
"""Return a very basic string representation"""
|
||||
return 'WmlIterator<' + repr(self.element) +', line %d>'%(self.lineno+1)
|
||||
|
||||
def next(self):
|
||||
"""Move the iterator to the next line number
|
||||
note: May raise StopIteration"""
|
||||
if not self.hasNext():
|
||||
if self.scopes:
|
||||
printError(self.fname, "reached EOF with open scopes", self.scopes)
|
||||
raise StopIteration
|
||||
self.lineno = self.lineno + self.span
|
||||
self.text, self.span = parseQuotes(self.lines, self.fname, self.lineno)
|
||||
self.scopes.extend(self.nextScopes)
|
||||
self.element, nextScopes = parseElements(self.text, self.fname, self.lineno, self.scopes)
|
||||
self.nextScopes = []
|
||||
for elem in nextScopes:
|
||||
# remember scopes by storing a copy of the iterator
|
||||
copyItor = self.copy()
|
||||
copyItor.element = elem
|
||||
self.nextScopes.append(copyItor)
|
||||
copyItor.nextScopes.append(copyItor)
|
||||
if(len(self.element) == 1):
|
||||
# currently we only wish to handle simple single assignment syntax
|
||||
self.element = self.element[0]
|
||||
if self.endScope is not None and not self.scopes.count(self.endScope):
|
||||
raise StopIteration
|
||||
return self
|
||||
|
||||
def iterScope(self):
|
||||
"""Return an iterator for the current scope"""
|
||||
if not self.scopes:
|
||||
return WmlIterator(self.lines, self.fname)
|
||||
scopeItor = self.scopes[-1].copy()
|
||||
scopeItor.endScope = self.scopes[-1]
|
||||
return scopeItor
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""Perform a test run on a file or directory"""
|
||||
import os, glob
|
||||
didSomething = False
|
||||
flist = sys.argv[1:]
|
||||
if not flist:
|
||||
print 'Current directory is', os.getcwd()
|
||||
flist = glob.glob(os.path.join(os.getcwd(), raw_input('Which file(s) would you like to test?\n')))
|
||||
while flist:
|
||||
fname = flist.pop()
|
||||
if os.path.isdir(fname):
|
||||
flist += glob.glob(fname + os.path.sep + '*')
|
||||
continue
|
||||
if not os.path.isfile(fname) or os.path.splitext(fname)[1] != '.cfg':
|
||||
continue
|
||||
print 'Reading', fname+'...'
|
||||
didSomething = True
|
||||
f = open(fname)
|
||||
itor = WmlIterator(f.readlines())
|
||||
for i in itor:
|
||||
pass
|
||||
f.close()
|
||||
print itor.lineno + itor.span, 'lines read.'
|
||||
if not didSomething:
|
||||
print 'That is not a valid .cfg file'
|
||||
if os.name == 'nt' and os.path.splitext(__file__)[0].endswith('wmliterator') and not sys.argv[1:]:
|
||||
os.system('pause')
|
||||
|
||||
# wmliterator.py ends here
|
||||
"""
|
||||
wmliterator.py -- Python routines for navigating a Battle For Wesnoth WML tree
|
||||
Author: Sapient (Patrick Parker), 2007
|
||||
"""
|
||||
import sys, re, copy
|
||||
keyPattern = re.compile('(\w+)(,\s?\w+)*\s*=')
|
||||
keySplit = re.compile(r'[=,\s]')
|
||||
tagPattern = re.compile(r'(^|(?<![\w\|\}]))(\[.*?\])')
|
||||
macroOpenPattern = re.compile(r'(\{[^\s\}]*)')
|
||||
macroClosePattern = re.compile(r'\}')
|
||||
|
||||
silenceErrors = {}
|
||||
|
||||
def wmlfind(element, wmlItor):
|
||||
"""Find a simple element from traversing a WML iterator"""
|
||||
for itor in wmlItor.copy():
|
||||
if element == itor.element:
|
||||
return itor
|
||||
return None
|
||||
|
||||
def wmlfindin(element, scopeElement, wmlItor):
|
||||
"""Find an element inside a particular type of scope element"""
|
||||
for itor in wmlItor.copy():
|
||||
if element == itor.element:
|
||||
if itor.scopes:
|
||||
if scopeElement == itor.scopes[-1].element:
|
||||
return itor
|
||||
elif not scopeElement:
|
||||
# allow searching in the empty scope
|
||||
return itor
|
||||
return None
|
||||
|
||||
def parseQuotes(lines, fname, lineno):
|
||||
"""Return the line or multiline text if a quote spans multiple lines"""
|
||||
text = lines[lineno]
|
||||
span = 1
|
||||
begincomment = text.find('#')
|
||||
if begincomment < 0:
|
||||
begincomment = None
|
||||
beginquote = text[:begincomment].find('"')
|
||||
while beginquote >= 0:
|
||||
endquote = -1
|
||||
beginofend = beginquote+1
|
||||
while endquote < 0:
|
||||
endquote = text.find('"', beginofend)
|
||||
if endquote < 0:
|
||||
if lineno + span >= len(lines):
|
||||
printError(fname, 'reached EOF due to unterminated string at line', lineno+1)
|
||||
return text, span
|
||||
text += lines[lineno + span]
|
||||
span += 1
|
||||
beginofend = text.rfind('\n', beginofend, len(text)-1)
|
||||
begincomment = text.find('#', endquote+1)
|
||||
if begincomment < 0:
|
||||
begincomment = None
|
||||
beginquote = text[:begincomment].find('"', endquote+1)
|
||||
return text, span
|
||||
|
||||
def isDirective(elem):
|
||||
"Identify things that shouldn't be indented."
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
for prefix in ("#ifdef", "#else", "#endif", "#define", "#enddef"):
|
||||
if elem.startswith(prefix):
|
||||
return True
|
||||
return False
|
||||
|
||||
def isCloser(elem):
|
||||
"Are we looking at a closing tag?"
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
return elem.startswith("[/")
|
||||
|
||||
def isOpener(elem):
|
||||
"Are we looking at an opening tag?"
|
||||
if isinstance(elem, WmlIterator):
|
||||
elem = elem.element
|
||||
return elem.startswith("[") and not isCloser(elem)
|
||||
|
||||
def closeScope(scopes, closerElement, fname, lineno):
|
||||
"""Close the most recently opened scope. Return false if not enough scopes.
|
||||
note: directives close all the way back to the last open directive
|
||||
non-directives cannot close a directive and will no-op in that case."""
|
||||
try:
|
||||
if isDirective(closerElement):
|
||||
while not isDirective(scopes.pop()):
|
||||
pass
|
||||
elif not isDirective(scopes[-1]):
|
||||
closed = scopes.pop()
|
||||
elem = closed
|
||||
if isinstance(closed, WmlIterator):
|
||||
elem = closed.element
|
||||
if ((isOpener(elem) and closerElement != '[/'+elem[1:]
|
||||
and '+'+closerElement != elem[1]+'[/'+elem[2:])
|
||||
or (elem.startswith('{') and closerElement.find('macro')<0)):
|
||||
printError(fname, 'reached', closerElement, 'at line', lineno+1, 'before closing scope', elem, '(%d)'%lineno)
|
||||
scopes.append(closed) # to reduce additional errors (hopefully)
|
||||
return True
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
def printError(fname, *misc):
|
||||
"""Print error associated with a given file; avoid printing duplicates"""
|
||||
if fname:
|
||||
silenceValue = ' '.join(map(str, misc))
|
||||
if fname not in silenceErrors:
|
||||
print >>sys.stderr, fname
|
||||
silenceErrors[fname] = set()
|
||||
elif silenceValue in silenceErrors[fname]:
|
||||
return # do not print a duplicate error for this file
|
||||
silenceErrors[fname].add(silenceValue)
|
||||
print >>sys.stderr, 'wmliterator:',
|
||||
for item in misc:
|
||||
print >>sys.stderr, item,
|
||||
print >>sys.stderr #terminate line
|
||||
|
||||
def printScopeError(elementType, fname, lineno):
|
||||
"""Print out warning if a scope was unable to close"""
|
||||
printError(fname, 'attempt to close empty scope at', elementType, 'line', lineno+1)
|
||||
|
||||
def parseElements(text, fname, lineno, scopes):
|
||||
"""Remove any closed scopes, return a list of element names
|
||||
and list of new unclosed scopes
|
||||
Element Types:
|
||||
tags: one of "[tag_name]" or "[/tag_name]"
|
||||
[tag_name] - opens a scope
|
||||
[/tag_name] - closes a scope
|
||||
keys: either "key=" or ("key1=", "key2=") for multi-assignment
|
||||
key= - does not affect the scope
|
||||
key1,key2= - multi-assignment returns multiple elements
|
||||
directives: one of "#ifdef", "#else", "#endif", "#define", "#enddef"
|
||||
#ifdef - opens a scope
|
||||
#else - closes a scope, also opens a new scope
|
||||
#endif - closes a scope
|
||||
#define - opens a scope
|
||||
#enddef - closes a scope
|
||||
macro calls: "{MACRO_NAME}"
|
||||
{MACRO_NAME - opens a scope
|
||||
} - closes a scope (not an element)
|
||||
"""
|
||||
closeMacroType = 'end of macro'
|
||||
elements = [] #(elementType, sortPos, scopeDelta)
|
||||
# first remove any quoted strings
|
||||
beginquote = text.find('"')
|
||||
while beginquote >= 0:
|
||||
endquote = text.find('"', beginquote+1)
|
||||
if endquote < 0:
|
||||
text = text[:beginquote]
|
||||
beginquote = -1 #terminate loop
|
||||
else:
|
||||
text = text[:beginquote] + text[endquote+1:]
|
||||
beginquote = text.find('"')
|
||||
# next remove any comments
|
||||
text = text.lstrip()
|
||||
commentSearch = 1
|
||||
if text.startswith('#ifdef'):
|
||||
return (['#ifdef'],)*2
|
||||
elif text.startswith('#else'):
|
||||
if not closeScope(scopes, '#else', fname, lineno):
|
||||
printScopeError('#else', fname, lineno)
|
||||
return (['#else'],)*2
|
||||
elif text.startswith('#endif'):
|
||||
if not closeScope(scopes, '#endif', fname, lineno):
|
||||
printScopeError('#endif', fname, lineno)
|
||||
return ['#endif'], []
|
||||
elif text.startswith('#define'):
|
||||
return (['#define'],)*2
|
||||
elif text.find('#enddef') >= 0:
|
||||
elements.append(('#enddef', text.find('#enddef'), -1))
|
||||
else:
|
||||
commentSearch = 0
|
||||
begincomment = text.find('#', commentSearch)
|
||||
if begincomment >= 0:
|
||||
text = text[:begincomment]
|
||||
#now find elements in a loop
|
||||
for m in tagPattern.finditer(text):
|
||||
delta = 1
|
||||
if isCloser(m.group(2)):
|
||||
delta = -1
|
||||
elements.append((m.group(2), m.start(), delta))
|
||||
for m in keyPattern.finditer(text):
|
||||
for i, k in enumerate(keySplit.split(m.group(0))):
|
||||
if k:
|
||||
elements.append((k+'=', m.start()+i, 0))
|
||||
for m in macroOpenPattern.finditer(text):
|
||||
elements.append((m.group(1)+'}', m.start(), 1))
|
||||
for m in macroClosePattern.finditer(text):
|
||||
elements.append((closeMacroType, m.start(), -1))
|
||||
#sort by start position
|
||||
elements.sort(key=lambda x:x[1])
|
||||
resultElements = []
|
||||
openedScopes = []
|
||||
for elem, sortPos, scopeDelta in elements:
|
||||
while scopeDelta < 0:
|
||||
if not(closeScope(openedScopes, elem, fname, lineno)\
|
||||
or closeScope(scopes, elem, fname, lineno)):
|
||||
printScopeError(elem, fname, lineno)
|
||||
scopeDelta += 1
|
||||
while scopeDelta > 0:
|
||||
openedScopes.append(elem)
|
||||
scopeDelta -= 1
|
||||
if elem != closeMacroType:
|
||||
resultElements.append(elem)
|
||||
return resultElements, openedScopes
|
||||
|
||||
class WmlIterator(object):
|
||||
"""Return an iterable WML navigation object.
|
||||
note: if changes are made to lines while iterating, this may produce
|
||||
unexpected results. In such case, seek() to the linenumber of a
|
||||
scope behind where changes were made.
|
||||
Important Attributes:
|
||||
lines - this is an internal list of all the physical lines
|
||||
scopes - this is an internal list of all open scopes (as iterators)
|
||||
note: when retreiving an iterator from this list, always
|
||||
use a copy to perform seek() or next(), and not the original
|
||||
element - the wml tag, key, or macro name for this logical line
|
||||
(in complex cases, this may be a tuple of elements...
|
||||
see parseElements for list of possible values)
|
||||
text - the exact text of this logical line, as it appears in the
|
||||
original source, and ending with a newline
|
||||
note: the logical line also includes multi-line quoted strings
|
||||
span - the number of physical lines in this logical line:
|
||||
always 1, unless text contains a multi-line quoted string
|
||||
lineno - a zero-based line index marking where this text begins
|
||||
"""
|
||||
def __init__(self, lines, fname=None, begin=-1, endScope=None):
|
||||
"Initialize a new WmlIterator"
|
||||
self.lines = lines
|
||||
self.fname = fname
|
||||
self.reset()
|
||||
self.seek(begin)
|
||||
|
||||
def __iter__(self):
|
||||
"""The magic iterator method"""
|
||||
return self
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Compare two iterators"""
|
||||
return cmp((self.fname, self.lineno, self.element),
|
||||
(other.fname, other.lineno, other.element))
|
||||
|
||||
def reset(self):
|
||||
"""Reset any line tracking information to defaults"""
|
||||
self.lineno = -1
|
||||
self.scopes = []
|
||||
self.nextScopes = []
|
||||
self.text = ""
|
||||
self.span = 1
|
||||
self.element = ""
|
||||
return self
|
||||
|
||||
def seek(self, lineno, clearEnd=True):
|
||||
"""Move the iterator to a specific line number"""
|
||||
if clearEnd:
|
||||
self.endScope = None
|
||||
if lineno < self.lineno:
|
||||
for scope in reversed(self.scopes):
|
||||
# if moving backwards, try to re-use a scope iterator
|
||||
if scope.lineno <= lineno:
|
||||
# copy the scope iterator's state to self
|
||||
self.__dict__ = dict(scope.__dict__)
|
||||
self.scopes = scope.scopes[:]
|
||||
self.nextScopes = scope.nextScopes[:]
|
||||
break
|
||||
else:
|
||||
# moving backwards past all scopes forces a reset
|
||||
self.reset()
|
||||
while self.lineno + self.span - 1 < lineno:
|
||||
self.next()
|
||||
return self
|
||||
|
||||
def hasNext(self):
|
||||
"""Some loops may wish to check this method instead of calling next()
|
||||
and handling StopIteration... note: inaccurate for ScopeIterators"""
|
||||
return len(self.lines) > self.lineno + self.span
|
||||
|
||||
def copy(self):
|
||||
"""Return a copy of this iterator"""
|
||||
itor = copy.copy(self)
|
||||
itor.scopes = self.scopes[:]
|
||||
itor.nextScopes = self.nextScopes[:]
|
||||
return itor
|
||||
|
||||
def __str__(self):
|
||||
"""Return a pretty string representation"""
|
||||
if self.lineno == -1:
|
||||
return 'beginning of file'
|
||||
loc = ' at line ' + str(self.lineno+1)
|
||||
if self.element:
|
||||
return str(self.element) + loc
|
||||
if self.text.strip():
|
||||
return 'text' + loc
|
||||
return 'whitespace' + loc
|
||||
|
||||
def __repr__(self):
|
||||
"""Return a very basic string representation"""
|
||||
return 'WmlIterator<' + repr(self.element) +', line %d>'%(self.lineno+1)
|
||||
|
||||
def next(self):
|
||||
"""Move the iterator to the next line number
|
||||
note: May raise StopIteration"""
|
||||
if not self.hasNext():
|
||||
if self.scopes:
|
||||
printError(self.fname, "reached EOF with open scopes", self.scopes)
|
||||
raise StopIteration
|
||||
self.lineno = self.lineno + self.span
|
||||
self.text, self.span = parseQuotes(self.lines, self.fname, self.lineno)
|
||||
self.scopes.extend(self.nextScopes)
|
||||
self.element, nextScopes = parseElements(self.text, self.fname, self.lineno, self.scopes)
|
||||
self.nextScopes = []
|
||||
for elem in nextScopes:
|
||||
# remember scopes by storing a copy of the iterator
|
||||
copyItor = self.copy()
|
||||
copyItor.element = elem
|
||||
self.nextScopes.append(copyItor)
|
||||
copyItor.nextScopes.append(copyItor)
|
||||
if(len(self.element) == 1):
|
||||
# currently we only wish to handle simple single assignment syntax
|
||||
self.element = self.element[0]
|
||||
if self.endScope is not None and not self.scopes.count(self.endScope):
|
||||
raise StopIteration
|
||||
return self
|
||||
|
||||
def iterScope(self):
|
||||
"""Return an iterator for the current scope"""
|
||||
if not self.scopes:
|
||||
return WmlIterator(self.lines, self.fname)
|
||||
scopeItor = self.scopes[-1].copy()
|
||||
scopeItor.endScope = self.scopes[-1]
|
||||
return scopeItor
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""Perform a test run on a file or directory"""
|
||||
import os, glob
|
||||
didSomething = False
|
||||
flist = sys.argv[1:]
|
||||
if not flist:
|
||||
print 'Current directory is', os.getcwd()
|
||||
flist = glob.glob(os.path.join(os.getcwd(), raw_input('Which file(s) would you like to test?\n')))
|
||||
while flist:
|
||||
fname = flist.pop()
|
||||
if os.path.isdir(fname):
|
||||
flist += glob.glob(fname + os.path.sep + '*')
|
||||
continue
|
||||
if not os.path.isfile(fname) or os.path.splitext(fname)[1] != '.cfg':
|
||||
continue
|
||||
print 'Reading', fname+'...'
|
||||
didSomething = True
|
||||
f = open(fname)
|
||||
itor = WmlIterator(f.readlines())
|
||||
for i in itor:
|
||||
pass
|
||||
f.close()
|
||||
print itor.lineno + itor.span, 'lines read.'
|
||||
if not didSomething:
|
||||
print 'That is not a valid .cfg file'
|
||||
if os.name == 'nt' and os.path.splitext(__file__)[0].endswith('wmliterator') and not sys.argv[1:]:
|
||||
os.system('pause')
|
||||
|
||||
# wmliterator.py ends here
|
||||
|
|
|
@ -1,271 +1,271 @@
|
|||
/*
|
||||
CSS stylesheet for XHTML produced by DocBook XSL stylesheets.
|
||||
Tested with XSL stylesheets 1.61.2, 1.67.2
|
||||
*/
|
||||
|
||||
span.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body blockquote {
|
||||
margin-top: .75em;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .75em;
|
||||
}
|
||||
|
||||
html body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
body div {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
div.toc p b,
|
||||
div.list-of-figures p b,
|
||||
div.list-of-tables p b,
|
||||
div.abstract p.title
|
||||
{
|
||||
color: #527bbd;
|
||||
font-family: tahoma, verdana, sans-serif;
|
||||
}
|
||||
|
||||
div.toc p:first-child,
|
||||
div.list-of-figures p:first-child,
|
||||
div.list-of-tables p:first-child,
|
||||
div.example p.title
|
||||
{
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
body h1 {
|
||||
margin: .0em 0 0 -4%;
|
||||
line-height: 1.3;
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
|
||||
body h2 {
|
||||
margin: 0.5em 0 0 -4%;
|
||||
line-height: 1.3;
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
|
||||
body h3 {
|
||||
margin: .8em 0 0 -3%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h4 {
|
||||
margin: .8em 0 0 -3%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h5 {
|
||||
margin: .8em 0 0 -2%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h6 {
|
||||
margin: .8em 0 0 -1%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body hr {
|
||||
border: none; /* Broken on IE6 */
|
||||
}
|
||||
div.footnotes hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
div.navheader th, div.navheader td, div.navfooter td {
|
||||
font-family: sans-serif;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
color: #527bbd;
|
||||
}
|
||||
div.navheader img, div.navfooter img {
|
||||
border-style: none;
|
||||
}
|
||||
div.navheader a, div.navfooter a {
|
||||
font-weight: normal;
|
||||
}
|
||||
div.navfooter hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
body td {
|
||||
line-height: 1.2
|
||||
}
|
||||
|
||||
body th {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ol {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ul, body dir, body menu {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body h1, body h2, body h3, body h4, body h5, body h6 {
|
||||
margin-left: 0
|
||||
}
|
||||
|
||||
body pre {
|
||||
margin: 0.5em 10% 0.5em 1em;
|
||||
line-height: 1.0;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
tt.literal, code.literal {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
.programlisting, .screen {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
margin: 0.5em 10% 0.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
background: #ffffee;
|
||||
margin: 1.0em 10% 0.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
div.sidebar * { padding: 0; }
|
||||
div.sidebar div { margin: 0; }
|
||||
div.sidebar p.title {
|
||||
font-family: sans-serif;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
div.bibliomixed {
|
||||
margin: 0.5em 5% 0.5em 1em;
|
||||
}
|
||||
|
||||
div.glossary dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
div.glossary dd p {
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: .8em 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
dt {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
dt span.term {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.variablelist dd p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.itemizedlist li, div.orderedlist li {
|
||||
margin-left: -0.8em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style-position: outside;
|
||||
}
|
||||
|
||||
div.sidebar ul, div.sidebar ol {
|
||||
margin-left: 2.8em;
|
||||
}
|
||||
|
||||
div.itemizedlist p.title,
|
||||
div.orderedlist p.title,
|
||||
div.variablelist p.title
|
||||
{
|
||||
margin-bottom: -0.8em;
|
||||
}
|
||||
|
||||
div.revhistory table {
|
||||
border-collapse: collapse;
|
||||
border: none;
|
||||
}
|
||||
div.revhistory th {
|
||||
border: none;
|
||||
color: #527bbd;
|
||||
font-family: tahoma, verdana, sans-serif;
|
||||
}
|
||||
div.revhistory td {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
/* Keep TOC and index lines close together. */
|
||||
div.toc dl, div.toc dt,
|
||||
div.list-of-figures dl, div.list-of-figures dt,
|
||||
div.list-of-tables dl, div.list-of-tables dt,
|
||||
div.indexdiv dl, div.indexdiv dt
|
||||
{
|
||||
line-height: normal;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Table styling does not work because of overriding attributes in
|
||||
generated HTML.
|
||||
*/
|
||||
div.table table,
|
||||
div.informaltable table
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-right: 5%;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
div.informaltable table
|
||||
{
|
||||
margin-top: 0.4em
|
||||
}
|
||||
div.table thead,
|
||||
div.table tfoot,
|
||||
div.table tbody,
|
||||
div.informaltable thead,
|
||||
div.informaltable tfoot,
|
||||
div.informaltable tbody
|
||||
{
|
||||
/* No effect in IE6. */
|
||||
border-top: 2px solid #527bbd;
|
||||
border-bottom: 2px solid #527bbd;
|
||||
}
|
||||
div.table thead, div.table tfoot,
|
||||
div.informaltable thead, div.informaltable tfoot
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.mediaobject img {
|
||||
border: 1px solid silver;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
div.figure p.title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div.navheader, div.navfooter { display: none; }
|
||||
}
|
||||
/*
|
||||
CSS stylesheet for XHTML produced by DocBook XSL stylesheets.
|
||||
Tested with XSL stylesheets 1.61.2, 1.67.2
|
||||
*/
|
||||
|
||||
span.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body blockquote {
|
||||
margin-top: .75em;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .75em;
|
||||
}
|
||||
|
||||
html body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
body div {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
div.toc p b,
|
||||
div.list-of-figures p b,
|
||||
div.list-of-tables p b,
|
||||
div.abstract p.title
|
||||
{
|
||||
color: #527bbd;
|
||||
font-family: tahoma, verdana, sans-serif;
|
||||
}
|
||||
|
||||
div.toc p:first-child,
|
||||
div.list-of-figures p:first-child,
|
||||
div.list-of-tables p:first-child,
|
||||
div.example p.title
|
||||
{
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
body h1 {
|
||||
margin: .0em 0 0 -4%;
|
||||
line-height: 1.3;
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
|
||||
body h2 {
|
||||
margin: 0.5em 0 0 -4%;
|
||||
line-height: 1.3;
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
|
||||
body h3 {
|
||||
margin: .8em 0 0 -3%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h4 {
|
||||
margin: .8em 0 0 -3%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h5 {
|
||||
margin: .8em 0 0 -2%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body h6 {
|
||||
margin: .8em 0 0 -1%;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
body hr {
|
||||
border: none; /* Broken on IE6 */
|
||||
}
|
||||
div.footnotes hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
div.navheader th, div.navheader td, div.navfooter td {
|
||||
font-family: sans-serif;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
color: #527bbd;
|
||||
}
|
||||
div.navheader img, div.navfooter img {
|
||||
border-style: none;
|
||||
}
|
||||
div.navheader a, div.navfooter a {
|
||||
font-weight: normal;
|
||||
}
|
||||
div.navfooter hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
body td {
|
||||
line-height: 1.2
|
||||
}
|
||||
|
||||
body th {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ol {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ul, body dir, body menu {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body h1, body h2, body h3, body h4, body h5, body h6 {
|
||||
margin-left: 0
|
||||
}
|
||||
|
||||
body pre {
|
||||
margin: 0.5em 10% 0.5em 1em;
|
||||
line-height: 1.0;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
tt.literal, code.literal {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
.programlisting, .screen {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
margin: 0.5em 10% 0.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
background: #ffffee;
|
||||
margin: 1.0em 10% 0.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
div.sidebar * { padding: 0; }
|
||||
div.sidebar div { margin: 0; }
|
||||
div.sidebar p.title {
|
||||
font-family: sans-serif;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
div.bibliomixed {
|
||||
margin: 0.5em 5% 0.5em 1em;
|
||||
}
|
||||
|
||||
div.glossary dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
div.glossary dd p {
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: .8em 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
dt {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
dt span.term {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.variablelist dd p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.itemizedlist li, div.orderedlist li {
|
||||
margin-left: -0.8em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style-position: outside;
|
||||
}
|
||||
|
||||
div.sidebar ul, div.sidebar ol {
|
||||
margin-left: 2.8em;
|
||||
}
|
||||
|
||||
div.itemizedlist p.title,
|
||||
div.orderedlist p.title,
|
||||
div.variablelist p.title
|
||||
{
|
||||
margin-bottom: -0.8em;
|
||||
}
|
||||
|
||||
div.revhistory table {
|
||||
border-collapse: collapse;
|
||||
border: none;
|
||||
}
|
||||
div.revhistory th {
|
||||
border: none;
|
||||
color: #527bbd;
|
||||
font-family: tahoma, verdana, sans-serif;
|
||||
}
|
||||
div.revhistory td {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
/* Keep TOC and index lines close together. */
|
||||
div.toc dl, div.toc dt,
|
||||
div.list-of-figures dl, div.list-of-figures dt,
|
||||
div.list-of-tables dl, div.list-of-tables dt,
|
||||
div.indexdiv dl, div.indexdiv dt
|
||||
{
|
||||
line-height: normal;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Table styling does not work because of overriding attributes in
|
||||
generated HTML.
|
||||
*/
|
||||
div.table table,
|
||||
div.informaltable table
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-right: 5%;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
div.informaltable table
|
||||
{
|
||||
margin-top: 0.4em
|
||||
}
|
||||
div.table thead,
|
||||
div.table tfoot,
|
||||
div.table tbody,
|
||||
div.informaltable thead,
|
||||
div.informaltable tfoot,
|
||||
div.informaltable tbody
|
||||
{
|
||||
/* No effect in IE6. */
|
||||
border-top: 2px solid #527bbd;
|
||||
border-bottom: 2px solid #527bbd;
|
||||
}
|
||||
div.table thead, div.table tfoot,
|
||||
div.informaltable thead, div.informaltable tfoot
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.mediaobject img {
|
||||
border: 1px solid silver;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
div.figure p.title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div.navheader, div.navfooter { display: none; }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue