Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F625647
DataHelper.pl
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
19 KB
Referenced Files
None
Subscribers
None
DataHelper.pl
View Options
#
DataHelper
contains
subroutines
useful
for
loading
a
character's
# frames, and creating his states.
use strict;
require '
FighterStats
.
pl';
=comment
SITUATIONS ARE:
Ready, Stand, Crouch, (Midair = any + character is flying), Falling
SITUATION DEPENDENT EVENTS ARE:
Highhit, Uppercut, Hit, Groinhit, Leghit, Fall
STANDBY EVENTS ARE:
Won, Hurt, Threat, Fun, Turn
________|___Ready___________Block___Stand___________Crouch______________Midair______Falling
Highhit | HighPunched - HighPunched KneelingPunched (...) (...)
Uppercut| Falling - Falling KneelingPunched (...) (...)
Hit | LowPunched - LowPunched KneelingKicked
Groinhit| GroinKicked - GroinKicked KneelingKicked
Leghit | Swept - Swept KneelingKicked
Fall | Falling - Falling KneelingPunched
FRAME MEMBER DESCRIPTION IS:
x int X coordinate offset of the image relative to the character's
anchor
.
y
int
Y
coordinate
offset
of
the
image
relative
to
the
character's anchor.
w int The width of the image.
h int The height of the image.
head array The coordinates of a polygon marking the head within the image, relative to the anchor.
body array The coordinates of a polygon marking the body within the image, relative to the anchor.
legs array The coordinates of a polygon marking the legs within the image, relative to the anchor.
hit array The coordinates of a polygon marking the hit within the image, relative to the anchor.
STATE MEMBER DESCRIPTION IS:
F int The number of the visible frame.
SITU string The situation associated with this state (Ready, Stand, Crouch, Falling)
DEL int The delay before moving to the next state.
NEXTST string The name of the state which follows this state, if none of the CONs is used.
CON hash Connections from this state. The keys are either events or keyboard input.
HIT ? The hit delivered at the beginning of this state.
BLOCK int If true, the character is blocking in his current state.
MOVE int The character's
anchor
should
continously
move
this
much
during
this
state
.
DELTAX
int
The
character's anchor should immediately change by this much after this state.
PUSHX int The character is pushed, with this much momentum upon entering this state.
TURN int If true, the character's
facing
direction
changes
after
this
state
.
JUMP
int
The
character
leaps
into
the
air
,
with
this
much
initial
momentum
upon
entering
this
state
.
DOODAD
string
A
doodad
is
created
at
the
beginning
of
this
state
.
The
string
contains
the
doodad's type and speed.
SOUND string The sound effect associated with this state (if any);
HITSND string The sound effect if the HIT is successful.
MISSSND string The sound effect if the HIT fails.
CODE string This code will be evaled at the beginning of this state.
LAYER int The "priority" of the graphics. 5: hurt; 10: block; 15: kneeling; 20: normal; 25: attack
=cut
# Loads the frame data (x, y, w, h) from the given datafile.
# The path to the datafile is inserted automatically. The frame data will
# be shifted by (-PivotX,-PivotY).
#
# Returns an array of frame data. The first element in the array is
# a dummy entry, the second is the first real entry. This is because
# the first thing in the datafile is a PAL entry.
#
# Example: LoadFrames( "ZOLIDATA.DAT.txt" );
sub LoadFrames ($$$)
{
my ($DataName, $PivotX, $PivotY) = @_;
my (@Frames, $data, $frame, $DatName);
# Make sure that Whatever.dat also exists.
$DatName = $DataName;
$DatName =~ s/\.txt$//;
open DATFILE, "../characters/$DatName" || die ("Couldn't
open
..
/
characters/
$
DatName
");
close DATFILE;
open DATAFILE, "
..
/
characters/
$
DataName
" || die ("
Couldn
't open ../characters/$DataName");
$data = '';
while ( read DATAFILE, $data, 16384, length($data) )
{
}
close DATAFILE;
print "$DataName file is ", length($data), " bytes long.\n";
# Insert a dummy first row for the palette entry
eval ("\@Frames = ( {}, $data);");
die $@ if $@;
foreach $frame (@Frames)
{
OffsetFrame( $frame, -$PivotX, -$PivotY );
}
print "$DataName loaded, ", scalar @Frames, " frames.\n";
return @Frames;
}
# Creates a frame lookup from a descriptor array.
# The first parameter is the expected number of frames.
# The descriptor array should have frame base names in even positions,
# and lengths at odd. positions. For example:
# ("start", 6, "stand", 4, ... )
#
# The routine will return a lookup which will contain the frame's
logical
#
name
as
a
key
,
and
its
physical
index
as
a
value
.
The
logical
names
are
#
simply
the
basename
plus
a
number
.
The
example
above
would
return
:
#
(
"start1"
=>
1
,
"start2"
=>
2
,
...,
"start6"
=>
6
,
"stand1"
=>
6
,
"stand2"
=>
7
,
...)
sub
CreateFrameLookup
{
my
(
$
ExpectedCount
,
@
FrameDesc
)
=
@
_
;
my
(
$
FrameName
,
$
NumFrames
);
my
(
$
i
,
$
j
);
my
(
%FrameLookup);
for
(
$
i
=
0
;
$
i
<
scalar
@
FrameDesc
;
$
i
+=
2
)
{
$
FrameName
=
$
FrameDesc
[
$
i
];
$
NumFrames
=
$
FrameDesc
[
$
i
+
1
];
for
(
$
j
=
1
;
$
j<=
$
NumFrames
;
++
$
j
)
{
#
print
"Frame "
,
(
scalar
keys
%FrameLookup) + 1, " is now called $FrameName$j\n";
print
"Name redefinition: $FrameName!\n"
if
defined
$
FrameLookup
{
"$FrameName$j"
};
$
FrameLookup
{
"$FrameName$j"
}
=
(
scalar
keys
%FrameLookup) + 1;
}
}
if
(
$
ExpectedCount
!
=
scalar
keys
(
%FrameLookup ) )
{
die
(
"Expected number of frames ($ExpectedCount) doesn't equal the actual number of frames: "
.
scalar
keys
(
%FrameLookup) );
}
return
%FrameLookup;
}
#
Helper
function
.
Finds
the
last
frame
with
a
given
name
in
a
frame
#
lookup
structure
.
Return
the
index
of
the
last
frame
(
1
-
based
),
or
#
0
if
none
with
the
given
name
were
found
.
#
#
Example
:
If
there
are
6
"highpunch"
frames
(
highpunch1
to
highpunch6
),
#
FindLastFrame
(
\
%FrameLookup, "highpunch") returns 6.
sub
FindLastFrame
(
$$
)
{
my
(
$
FrameLookup
,
$
FrameName
)
=
@
_
;
my
(
$
i
)
=
(
1
);
while
(
exists
$
{
$
FrameLookup
}{
"$FrameName$i"
}
)
{
$
i++
;
}
return
$
i
-
1
;
}
sub
OffsetPolygon
(
$$$
)
{
my
(
$
poly
,
$
dx
,
$
dy
)
=
@
_
;
my
(
$
i
,
$
n
);
$
n
=
scalar
@
{
$
poly
};
for
(
$
i
=
0
;
$
i
<
$
n
;
$
i+=
2
)
{
$
poly->
[
$
i
]
+=
$
dx
;
$
poly->
[
$
i
+
1
]
+=
$
dy
;
}
}
sub
MirrorPolygon
(
$
)
{
my
(
$
poly
)
=
@
_
;
my
(
$
i
,
$
n
);
$
n
=
scalar
@
{
$
poly
};
for
(
$
i
=
0
;
$
i
<
$
n
;
$
i+=
2
)
{
$
poly->
[
$
i
]
=
-
$
poly->
[
$
i
];
}
}
sub
GetPolygonCenter
(
$
)
{
my
(
$
poly
)
=
@
_
;
my
(
$
i
,
$
n
,
$
x
,
$
y
);
$
n
=
scalar
@
{
$
poly
};
$
x
=
$
y
=
0
;
for
(
$
i
=
0
;
$
i
<
$
n
;
$
i+=
2
)
{
$
x
+=
$
poly->
[
$
i
];
$
y
+=
$
poly->
[
$
i
+
1
];
}
return
(
$
x
*
2
/
$
n
,
$
y
*
2
/
$
n
);
}
sub
OffsetFrame
(
$$$
)
{
my
(
$
frame
,
$
dx
,
$
dy
)
=
@
_
;
$
frame->
{
'x'
}
+=
$
dx
;
$
frame->
{
'y'
}
+=
$
dy
;
OffsetPolygon
(
$
frame->
{
head
},
$
dx
,
$
dy
)
if
defined
(
$
frame->
{
head
});
OffsetPolygon
(
$
frame->
{
body
},
$
dx
,
$
dy
)
if
defined
(
$
frame->
{
body
});
OffsetPolygon
(
$
frame->
{
legs
},
$
dx
,
$
dy
)
if
defined
(
$
frame->
{
legs
});
OffsetPolygon
(
$
frame->
{
hit
},
$
dx
,
$
dy
)
if
defined
(
$
frame->
{
hit
});
}
#
FindLastState
returns
the
last
index
of
a
given
state
.
#
For
example
,
if
Punch4
is
the
last
in
Punch
,
FindLastState
(
"Punch"
)
is
4.
sub
FindLastState
(
$$
)
{
my
(
$
States
,
$
StateName
)
=
@
_
;
my
(
$
i
)
=
(
1
);
while
(
exists
$
{
$
States
}{
"$StateName $i"
}
)
{
$
i++
;
}
return
$
i
-
1
;
}
#
Translates
an
abbreviated
sequence
to
a
full
sequence
.
#
"-punch"
is
every
punch
frame
backwards
.
#
"_punch"
is
every
punch
frame
except
the
last
one
backwards
.
#
"+punch"
is
every
punch
frame
forwards
.
sub
TranslateSequence
(
$$
)
{
my
(
$
FrameLookup
,
$
Sequence
)
=
@
_
;
my
(
$
pre
,
$
frame
)
=
$
Sequence
=~
/^
([
+-
_
]{
0
,
1
})(
\w+
)
/
;
my
(
$
LastFrame
)
=
(
FindLastFrame
(
$
FrameLookup
,
$
frame
)
);
#
$
LastFrame
=
(
FindLastFrame
(
$
FrameLookup
,
"$pre$frame"
)
)
if
$
LastFrame
==
0
;
#print
"Last frame of $frame is $LastFrame.\n"
;
return
"$frame 1-$LastFrame"
if
(
$
pre
eq
'+'
);
return
"$frame $LastFrame-1"
if
(
$
pre
eq
'-'
);
return
"$frame "
.
(
$
LastFrame
-
1
)
.
"-1"
if
(
$
pre
eq
'_'
);
$
Sequence
=~
s/\
sn
(
-
{
0
,
1
})
/
$
LastFrame
$
1
/
;
#
Replace
n
-
with
last
frame
$
Sequence
=~
s/-n/-
$
LastFrame
/
;
#
Replace
-
n
with
last
frame
return
$
Sequence
;
}
sub
SetStateData
(
$$$
)
{
my
(
$
state
,
$
FrameDesc
,
$
suffix
)
=
@
_
;
$
state->
{
DEL
}
=
$
FrameDesc
->
{
"DEL$suffix"
}
if
defined
$
FrameDesc
->
{
"DEL$suffix"
};
$
state->
{
HIT
}
=
$
FrameDesc
->
{
"HIT$suffix"
}
if
defined
$
FrameDesc
->
{
"HIT$suffix"
};
$
state->
{
CON
}
=
$
FrameDesc
->
{
"CON$suffix"
}
if
defined
$
FrameDesc
->
{
"CON$suffix"
};
$
state->
{
BLOCK
}
=
$
FrameDesc
->
{
"BLOCK$suffix"
}
if
defined
$
FrameDesc
->
{
"BLOCK$suffix"
};
$
state->
{
NEXTST
}
=
$
FrameDesc
->
{
"NEXTST$suffix"
}
if
defined
$
FrameDesc
->
{
"NEXTST$suffix"
};
$
state->
{
MOVE
}
=
$
FrameDesc
->
{
"MOVE$suffix"
}
if
defined
$
FrameDesc
->
{
"MOVE$suffix"
};
$
state->
{
DELTAX
}
=
$
FrameDesc
->
{
"DELTAX$suffix"
}
if
defined
$
FrameDesc
->
{
"DELTAX$suffix"
};
$
state->
{
PUSHX
}
=
$
FrameDesc
->
{
"PUSHX$suffix"
}
if
defined
$
FrameDesc
->
{
"PUSHX$suffix"
};
$
state->
{
TURN
}
=
$
FrameDesc
->
{
"TURN$suffix"
}
if
defined
$
FrameDesc
->
{
"TURN$suffix"
};
$
state->
{
JUMP
}
=
$
FrameDesc
->
{
"JUMP$suffix"
}
if
defined
$
FrameDesc
->
{
"JUMP$suffix"
};
$
state->
{
SITU
}
=
$
FrameDesc
->
{
"SITU$suffix"
}
if
defined
$
FrameDesc
->
{
"SITU$suffix"
};
$
state->
{
DOODAD
}
=
$
FrameDesc
->
{
"DOODAD$suffix"
}
if
defined
$
FrameDesc
->
{
"DOODAD$suffix"
};
$
state->
{
SOUND
}
=
$
FrameDesc
->
{
"SOUND$suffix"
}
if
defined
$
FrameDesc
->
{
"SOUND$suffix"
};
$
state->
{
CODE
}
=
$
FrameDesc
->
{
"CODE$suffix"
}
if
defined
$
FrameDesc
->
{
"CODE$suffix"
};
}
#
Adds
a
sequence
to
the
end
of
a
state
#
Sequences
are
:
e
.
g
.
"throw 10-14, throw 16, throw 14-10"
#
Each
piece
of
the
sequence
will
have
$
Delay
delay
.
sub
AddStates
(
$$$
)
{
my
(
$
States
,
$
Frames
,
$
FrameDesc
)
=
@
_
;
my
(
$
StateName
,
$
SequenceString
,
$
LastState
,
$
i
,
$
sloop
,
$
s
,
@
Sequences
);
my
(
$
from
,
$
to
,
$
frame
,
$
state
);
$
StateName
=
$
FrameDesc
->
{
'N'
};
$
SequenceString
=
$
FrameDesc
->
{
'S'
};
$
FrameDesc
->
{
SITU
}
=
'Stand'
unless
defined
$
FrameDesc
->
{
SITU
};
$
LastState
=
FindLastState
(
$
States
,
$
StateName
)
+
1
;
@
Sequences
=
split
(
/\s*
,
\s*/
,
$
SequenceString
);
for
(
$
sloop
=
0
;
$
sloop
<
scalar
@
Sequences
;
++
$
sloop
)
{
$
s
=
TranslateSequence
(
$
Frames
,
$
Sequences
[
$
sloop
]
);
#print
"Sequence is $s\n"
;
if
(
$
s
=~
/^\s*
(
\w+
)
\s+
(
\d+
)
-
(
\d+
)
\s*
$
/
)
{
#
Sequence
is
'<frame> <from>-<to>'
$
frame
=
$
1
;
$
from
=
$
2
;
$
to
=
$
3
;
}
elsif
(
$
s
=~
/^\s*
(
\w+
)
\s+
(
\d+
)
\s*
$
/
)
{
#
Sequence
is
'<frame> <number>'
$
frame
=
$
1
;
$
from
=
$
to
=
$
2
;
}
else
{
die
"Sequence '$s' incorrect.\n"
;
}
$
i
=
$
from
;
while
(
1
)
{
die
"Error: Frame $frame$i doesn't exist.\n"
unless
defined
$
{
$
Frames
}{
"$frame$i"
};
$
state
=
{
'F'=>
"$frame$i"
};
SetStateData
(
$
state
,
$
FrameDesc
,
''
);
SetStateData
(
$
state
,
$
FrameDesc
,
$
LastState
);
if
(
(
$
sloop
==
scalar
@
Sequences
-
1
)
and
(
$
i
==
$
to
)
)
{
SetStateData
(
$
state
,
$
FrameDesc
,
'N'
);
}
$
States
->
{
"$StateName $LastState"
}
=
$
state
;
#
print
"Added state '$StateName $LastState' as frame '$frame$i', delay $Delay\n"
;
$
LastState
++
;
if
(
$
from
<
$
to
)
{
$
i++
;
last
if
$
i
>
$
to
;
}
else
{
$
i--
;
last
if
$
i
<
$
to
;
}
}
}
}
sub
BlockStates
(
$$
)
{
my
(
$
frames
,
$
del
)
=
@
_
;
my
(
$
retval
,
$
i
);
#
We
need
to
make
sure
that
blocking
is
the
same
speed
for
every
character
.
#
Typical
is
5
frames
,
+-
1
frame
$
del
=
int
(
25
/
$
frames
);
#
1
/
1
$
retval
=
{
'N'=>'Block'
,
'DEL'=>
$
del
,
'S'=>'+block'
,
};
for
(
$
i
=
1
;
$
i
<=
$
frames
;
++
$
i
)
{
$
retval->
{
"NEXTST$i"
}
=
"Block "
.
(
$
i
-
1
);
$
retval->
{
"CON$i"
}
=
{
'block'=>
"Block "
.
(
$
i
+
1
)
};
$
retval->
{
"BLOCK$i"
}
=
1
if
$
i*
$
del
>
10
;
}
$
retval->
{
'NEXTST1'
}
=
'Stand'
;
$
retval->
{
"CON$frames"
}
=
{
'block'=>
"Block "
.
$
frames
};
return
$
retval
;
}
sub
KneelingStates
(
$$$$
)
{
my
(
$
frames
,
$
frames2
,
$
del
,
$
con
)
=
@
_
;
my
(
$
retval
,
$
retval2
,
$
i
,
$
j
);
$
retval
=
{
'N'=>'Kneeling'
,
'DEL'=>
$
del
,
'S'
=>
'+kneeling'
,
'SITU'=>'Crouch'
};
for
(
$
i
=
1
;
$
i
<=
$
frames
;
++
$
i
)
{
$
retval->
{
"NEXTST$i"
}
=
"Kneeling "
.
(
$
i
-
1
);
$
retval->
{
"CON$i"
}
=
{
'down'
=>
"Kneeling "
.
(
$
i
+
1
)
};
}
$
retval->
{
'NEXTST1'
}
=
'Stand'
;
$
retval->
{
"CON$frames"
}
=
{
'down'
=>
"Onknees"
};
$
retval2
=
{
'N'=>'Onknees'
,
'DEL'=>
$
del
,
'S'
=>
'+onknees,-onknees'
,
'SITU'=>'Crouch'
,
'NEXTST'
=>
"Kneeling $frames"
};
$
frames2
*=
2
;
for
(
$
i
=
1
;
$
i
<=
$
frames2
;
++
$
i
)
{
$
j
=
(
$
i
% $frames2) + 1;
$
retval2->
{
"CON$i"
}
=
{
%{$con}, 'down'=>"Onknees $j", 'forw'=>"Onknees $j", 'back'=>"Onknees $j" };
}
return
(
$
retval
,
$
retval2
);
}
sub
JumpStates
(
$$
)
{
my
(
$
frames
,
$
con
)
=
@
_
;
my
(
$
kneelingframes
,
$
onkneesframes
,
$
kickframes
,
$
punchframes
)
=
(
FindLastFrame
(
$
frames
,
'kneeling'
),
FindLastFrame
(
$
frames
,
'onknees'
),
FindLastFrame
(
$
frames
,
'kneelingkick'
),
FindLastFrame
(
$
frames
,
'kneelingpunch'
)
);
my
(
$
jumpheight
)
=
120
;
my
(
$
i
,
$
j
,
$
statestotal
,
$
statesdown
,
$
statesknees
,
$
deldown
,
$
jump
,
$
jumpfw
,
$
jumpbw
,
$
flying
,
$
flyingsequence
,
$
flyingstart
,
$
jumpkick
,
$
jumppunch
);
#
The
jump's first part is going down on knees, second part is
# on knees, third part is getting up.
if ( $::DELMULTIPLIER )
{
$statestotal = $jumpheight * 2 / 3 / $::DELMULTIPLIER; # 1/1
}
else
{
$statestotal = $jumpheight * 2 / 3;
}
$statesdown = $statestotal / 4;
$deldown = int($statesdown / $kneelingframes + 0.1); # 1/1
$statesdown = $deldown * $kneelingframes;
$statesknees = $statestotal - $statesdown * 2;
$jump = { '
N
'=>'
Jump
', '
DEL
'=> $deldown, '
S
'=>'kneeling
1
-
2
,
kneeling
1
',
'
JUMPN
'=>$jumpheight, NEXTSTN=>'
JumpFly
', '
SOUND1
'=>'slip4
.
voc', };
$jumpfw = { %{$jump}, '
N
'=>'
JumpFW
', '
PUSHX3
'=>18*16 };
$jumpbw = { %{$jump}, '
N
'=>'
JumpBW
', '
PUSHX3
'=>-9*16 };
$flyingsequence = '';
$flying = {};
for ( $i = 0; $i < $statesknees / $deldown; ++$i ) #1/1
{
$j = $i + $statesdown / $deldown; #1/1
$flyingsequence .= 'onknees
1
,
';
$flying->{"CON$j"} = $con;
# $flying->{"DEL$j"} = 1;
}
$flyingsequence = "+kneeling, $flyingsequence -kneeling";
$flying = { %{$flying}, '
N
'=>'
JumpFly
', '
DEL
'=> $deldown, '
S
'=>$flyingsequence,
'
DELN
'=>100 };
$flyingstart = { '
N
'=>'
JumpStart
', '
JUMP2
'=>$jumpheight, '
PUSHX2
'=>9*16, '
DEL1
'=>1,
'
DEL
'=> $deldown, '
S
'=>"stand 1,$flyingsequence", '
DELN
'=>100 };
print join( '
,
', %{$flying}), "\n";
$jumpkick = { '
N
'=>'
JumpKick
', '
HIT
'=>'
Fall
',
'
DEL
'=> int( $statestotal * 2 / 3 / ( $kickframes + $kneelingframes*2 + 3 ) ), # 1/1
'
S
'=> '
+
kneelingkick
,
kneelingkick
n
,
kneelingkick
n
,
kneelingkick
n
,
-
kneelingkick
,
-
kneeling',
'
HIT
'=>'
Fall
', '
DELN
'=>100 };
$jumppunch = { '
N
'=>'
JumpPunch
', '
HIT
'=>'
Highhit
',
'
DEL
'=> int( $statestotal * 2 / 3 / ( $punchframes + $kneelingframes*2 + 3 ) ), # 1/1
'
S
'=> '
+
kneelingpunch
,
kneelingpunch
n
,
kneelingpunch
n
,
kneelingpunch
n
,
-
kneelingpunch
,
-
kneeling',
'
HIT
'=>'
Fall
', '
DELN
'=>100 };
return ($jump, $jumpfw, $jumpbw, $flying, $flyingstart, $jumpkick, $jumppunch);
}
sub WalkingFrames($$$$$)
{
my ( $frameLookup, $frameArray, $preFrames, $distance, $con ) = @_;
my ( $walkFrames, $totalFrames, $seq, $seq2, $distPerFrame,
$walk, $back, $walkNextst, $backNextst,
$i, $j, );
$totalFrames = FindLastFrame( $frameLookup, 'walk' );
$walkFrames = $totalFrames - $preFrames;
if ( $preFrames > 0 ) {
$seq = "+walk, walk $preFrames-1";
$seq2 = "walk 1-$preFrames, -walk";
} else {
$seq = "+walk";
$seq2 = "-walk";
}
$walk = { '
N
'=>'
Walk
', '
S
'=>$seq, '
DEL
'=>5, '
CON
'=>$con };
$back = { '
N
'=>'
Back
', '
S
'=>$seq2, '
DEL
'=>5, };
# Add attributes for the 'pre' states.
for ( $i=1; $i <= $preFrames; ++$i )
{
$j = $i + 1;
$walk->{"CON$i"} = { %{$con}, 'forw' => "Walk $j" };
$walk->{"NEXTST$i"} = '
Stand
';
$back->{"CON$i"} = { %{$con}, 'back' => "Back $j" };
$back->{"NEXTST$i"} = '
Stand
';
}
# Add attributes for the 'walk' states.
$walkNextst = $preFrames ? '
Walk
' . ($totalFrames+1) : '
Stand
';
$backNextst = $preFrames ? '
Back
' . ($totalFrames+1) : '
Stand
';
$distPerFrame = $distance / $walkFrames; # 1/1
print "*** $preFrames $walkFrames $totalFrames $walkNextst $backNextst\n";
for ( $i=$preFrames+1; $i <= $totalFrames; ++$i )
{
$j = ($i == $totalFrames) ? $preFrames+1 : $i+1;
$walk->{"MOVE$i"} = 4;
$walk->{"NEXTST$i"} = $walkNextst;
$walk->{"CON$i"} = { %{$con}, 'forw' => "Walk $j" };
$back->{"MOVE$i"} = -4;
$back->{"NEXTST$i"} = $backNextst;
$back->{"CON$i"} = { %{$con}, 'back' => "Back $j" };
OffsetFrame( $frameArray->[$frameLookup->{"walk$i"}],
- ($i-$preFrames-1) * $distPerFrame, 0 );
}
return ( $walk, $back );
}
sub TravelingStates( $$$$$$ )
{
my ( $frameLookup, $frameArray, $states, $frameName, $from, $to ) = @_;
$from = 1 unless $from;
unless ( $to )
{
$to = FindLastFrame( $frameLookup, $frameName );
$to += 1 if $frameName eq 'falling';
}
my ( $fromIndex, $toIndex, $fromFrame, $toFrame, $fromOffset, $toOffset,
$deltax, $i, $state, $nextst );
# 1. Calculate the 'deltax' and 'fromOffset'.
$fromIndex = $frameLookup->{"$frameName$from"};
die "couldn't
find
frame
$
frameName$from
" unless defined $fromIndex;
$toIndex = $fromIndex - $from + $to;
$fromFrame = $frameArray-> [ $fromIndex ];
$toFrame = $frameArray-> [ $toIndex ];
$fromOffset = $fromFrame->{x} + ($fromFrame->{w} >> 1);
$toOffset = $toFrame->{x} + ($toFrame->{w} >> 1);
$deltax = ( $toOffset - $fromOffset ) / ( $to - $from ); #1/1
# print "
Offsets
:
$
fromOffset
$
toOffset
$
deltax\n
";
# 2. Offset every relevant frame.
for ( $i=$fromIndex; $i<=$toIndex; ++$i )
{
# print "
Offsetting
frame
$
i
by
", - $fromOffset - $deltax * ($i-$fromIndex), "
\n
";
OffsetFrame( $frameArray->[$i],
- $fromOffset - $deltax * ($i-$fromIndex), 0 );
}
# 3. Apply deltax to every relevant state.
while ( ($i, $state) = each %{$states} )
{
if ( $state->{F} >= $fromIndex and $state->{F} <= $toIndex )
{
$nextst = $states->{$state->{NEXTST}};
if ( defined($nextst) and $nextst->{F} >= $fromIndex and $nextst->{F} <= $toIndex )
{
$state->{DELTAX} = $deltax * ($nextst->{F} - $state->{F});
# print "
Fixing
state
$
i
:
deltax
=
", $state->{DELTAX}, "
\n
"
;
}
}
}
}
sub
FixStates
(
$$
)
{
my
(
$
frameLookup
,
$
states
)
=
@
_
;
my
(
$
framename
,
$
st
,
$
lastchar
,
$
key
,
$
value
,
$
nextchar
,
$
nextst
);
while
((
$
key
,
$
value
)
=
each
%{$states})
{
$
framename
=
$
value->
{
'F'
};
unless
(
$
framename
=~/^\d+
$
/
)
{
#
Convert
non
-
numeric
frames
to
their
numeric
counterparts
.
die
"Can't find image $framename in frame $key"
unless
defined
$
frameLookup->
{
$
framename
};
$
value->
{
'F'
}
=
$
frameLookup->
{
$
framename
};
}
(
$
st
,
$
lastchar
)
=
$
key
=~
/
(
\w+
)
\s+
(
\d+
)
/
;
unless
(
defined
$
value->
{
'NEXTST'
}
)
{
$
nextchar
=
$
lastchar
+
1
;
$
nextst
=
"$st $nextchar"
;
unless
(
defined
$
states->
{
$
nextst
}
)
{
#
print
"Go to Standby after $key\n"
;
$
nextst
=
'Stand'
;
}
$
value->
{
'NEXTST'
}
=
$
nextst
;
}
}
}
sub
FindShorthands
(
$
)
{
my
(
$
states
)
=
@
_
;
my
(
$
key
,
$
value
,
$
st
,
$
lastchar
,
%Shorthands );
while
((
$
key
,
$
value
)
=
each
%{$states})
{
(
$
st
,
$
lastchar
)
=
$
key
=~
/
(
\w+
)
\s+
(
\d+
)
/
;
print
"$key has no lastchar"
unless
defined
$
lastchar
;
if
(
$
lastchar
==
1
)
{
$
Shorthands
{
$
st
}
=
$
states->
{
$
key
};
}
}
return
%Shorthands;
}
sub
CheckStates
(
$$
)
{
my
(
$
fightername
,
$
states
)
=
@
_
;
my
(
$
key
,
$
state
,
$
con
);
my
(
$
seq
,
$
nextst
);
while
((
$
key
,
$
state
)
=
each
%{$states})
{
die
"Bad connection in fighter $fightername to '$state->{NEXTST} from $key!'"
unless
exists
$
states->
{
$
state->
{
NEXTST
}
};
next
unless
$
state->
{
CON
};
$
con
=
$
state->
{
CON
};
while
((
$
seq
,
$
nextst
)
=
each
%{$con})
{
die
"Bad connection in fighter $fightername to '$nextst' from $key!"
unless
exists
$
states->
{
$
nextst
};
}
}
}
return
1
;
File Metadata
Details
Attached
Mime Type
text/x-ruby
Expires
Sat, Nov 14, 11:43 PM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
136030
Default Alt Text
DataHelper.pl (19 KB)
Attached To
Mode
R76 OpenMortal
Attached
Detach File
Event Timeline