Added jobs in dockyards (WIP)
This commit is contained in:
parent
993ed0e897
commit
0feba35db0
|
@ -811,8 +811,8 @@
|
|||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter7229-3"
|
||||
x="-0.2"
|
||||
y="-0.2"
|
||||
x="-0.25"
|
||||
y="-0.25"
|
||||
height="1.5"
|
||||
width="1.5">
|
||||
<feFlood
|
||||
|
@ -872,6 +872,237 @@
|
|||
fx="349.2796"
|
||||
fy="150.05988"
|
||||
r="3.9959407" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5802">
|
||||
<path
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/options/background.png"
|
||||
style="display:inline;fill:#2c353d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7512);enable-background:new"
|
||||
d="M 475.82605,190.2261 H 1444.174 l -93.4957,699.5478 H 569.3217 Z"
|
||||
id="path5804"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(0.34038154,0,0,0.34038154,19.662314,-53.825672)" />
|
||||
</clipPath>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter7193">
|
||||
<feFlood
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(255,255,255)"
|
||||
result="flood"
|
||||
id="feFlood7183" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite7185" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="0.4"
|
||||
result="blur"
|
||||
id="feGaussianBlur7187" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset7189" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite7191" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter6138">
|
||||
<feFlood
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(255,255,255)"
|
||||
result="flood"
|
||||
id="feFlood6128" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite6130" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="0.4"
|
||||
result="blur"
|
||||
id="feGaussianBlur6132" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset6134" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite6136" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Dialog shadow"
|
||||
id="filter7512">
|
||||
<feFlood
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood7502" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite7504" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="33.649999999999999"
|
||||
result="blur"
|
||||
id="feGaussianBlur7506" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset7508" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite7510" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter5500-2"
|
||||
x="-0.2"
|
||||
y="-0.2"
|
||||
width="1.4"
|
||||
height="1.4">
|
||||
<feFlood
|
||||
flood-opacity="0.556863"
|
||||
flood-color="rgb(255,255,255)"
|
||||
result="flood"
|
||||
id="feFlood5490-9" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite5492-1" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1.1"
|
||||
result="blur"
|
||||
id="feGaussianBlur5494-2" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset5496-7" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite5498-0" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter5500-3"
|
||||
x="-0.20000000000000001"
|
||||
y="-0.20000000000000001"
|
||||
width="1.3999999999999999"
|
||||
height="1.3999999999999999">
|
||||
<feFlood
|
||||
flood-opacity="0.556863"
|
||||
flood-color="rgb(255,255,255)"
|
||||
result="flood"
|
||||
id="feFlood5490-6" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite5492-0" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1.1"
|
||||
result="blur"
|
||||
id="feGaussianBlur5494-6" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset5496-2" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite5498-6" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter6297"
|
||||
x="-0.20000000000000001"
|
||||
y="-0.20000000000000001"
|
||||
width="1.3999999999999999"
|
||||
height="1.3999999999999999">
|
||||
<feFlood
|
||||
flood-opacity="0.556863"
|
||||
flood-color="rgb(255,255,255)"
|
||||
result="flood"
|
||||
id="feFlood6287" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite6289" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1.1"
|
||||
result="blur"
|
||||
id="feGaussianBlur6291" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="0"
|
||||
result="offset"
|
||||
id="feOffset6293" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite6295" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter6390"
|
||||
x="-0.0936"
|
||||
width="1.1872"
|
||||
y="-0.0936"
|
||||
height="1.1872">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.1866562"
|
||||
id="feGaussianBlur6392" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
|
@ -880,11 +1111,11 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.0000001"
|
||||
inkscape:cx="221.23289"
|
||||
inkscape:cy="353.88524"
|
||||
inkscape:zoom="0.70710682"
|
||||
inkscape:cx="728.12591"
|
||||
inkscape:cy="574.187"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g7264"
|
||||
inkscape:current-layer="g6210"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:snap-bbox="true"
|
||||
|
@ -893,8 +1124,10 @@
|
|||
showguides="false"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-object-midpoints="true">
|
||||
inkscape:snap-global="false"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:measure-start="551.543,453.963"
|
||||
inkscape:measure-end="1261.48,449.72">
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
orientation="0,1920"
|
||||
|
@ -1979,4 +2212,400 @@
|
|||
style="fill:#43535c;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.23345587px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="Mission dialog"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g6210"
|
||||
transform="translate(-4.1823501,30.369099)">
|
||||
<path
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/common/dialog.png"
|
||||
style="display:inline;fill:#2c353d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7512);enable-background:new"
|
||||
d="M 475.82605,190.2261 H 1444.174 l -93.4957,699.5478 H 569.3217 Z"
|
||||
id="rect4931"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(0.34038154,0,0,0.34038154,-68.583942,-71.300136)" />
|
||||
<g
|
||||
clip-path="url(#clipPath5802)"
|
||||
inkscape:export-ydpi="91.800003"
|
||||
inkscape:export-xdpi="91.800003"
|
||||
inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/common/dialog-close1.png"
|
||||
id="g5454"
|
||||
style="display:inline;opacity:1"
|
||||
transform="translate(-88.246252,-17.474463)">
|
||||
<circle
|
||||
style="fill:#151c22;fill-opacity:1;stroke:#c1c1c1;stroke-width:0.79374999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter7193)"
|
||||
id="path7854"
|
||||
cx="508"
|
||||
cy="11.249985"
|
||||
r="20.847025" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.58333397px;line-height:6.61458349px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:0px;word-spacing:0px;fill:#d5c5ae;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7193)"
|
||||
x="496.83798"
|
||||
y="22.792192"
|
||||
id="text7862"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7860"
|
||||
x="496.83798"
|
||||
y="22.792192"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#d5c5ae;fill-opacity:1;stroke-width:0.26458335px">X</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b8d2f1;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="223.79375"
|
||||
y="20.359943"
|
||||
id="text6214"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6212"
|
||||
x="223.79375"
|
||||
y="20.359943"
|
||||
style="fill:#b8d2f1;fill-opacity:1;stroke-width:0.26458335px">Active jobs</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b8d2f1;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="213.62073"
|
||||
y="116.95998"
|
||||
id="text6218"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6216"
|
||||
x="213.62073"
|
||||
y="116.95998"
|
||||
style="fill:#b8d2f1;fill-opacity:1;stroke-width:0.26458335px">Proposed jobs</tspan></text>
|
||||
<g
|
||||
id="g6630"
|
||||
transform="translate(0,7.4083337)">
|
||||
<use
|
||||
transform="translate(0,23.881537)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use6334"
|
||||
inkscape:transform-center-y="-0.66101504"
|
||||
xlink:href="#use6271"
|
||||
y="0"
|
||||
x="0" />
|
||||
<g
|
||||
id="g6499">
|
||||
<text
|
||||
id="text6338"
|
||||
y="51.764362"
|
||||
x="152.35658"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.76111126px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="51.764362"
|
||||
x="152.35658"
|
||||
id="tspan6336"
|
||||
sodipodi:role="line">Escort a merchant transport to Rhinard</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.05555582px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="152.35658"
|
||||
y="61.289371"
|
||||
id="text6342"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6340"
|
||||
x="152.35658"
|
||||
y="61.289371"
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Reward : 500 zotys</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g6622"
|
||||
transform="translate(0,7.4083337)">
|
||||
<use
|
||||
transform="translate(121.04306,-195.15429)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use6271"
|
||||
inkscape:transform-center-y="-0.66101504"
|
||||
xlink:href="#path7197"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<g
|
||||
id="g6493">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="152.35658"
|
||||
y="27.882824"
|
||||
id="text6332"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6330"
|
||||
x="152.35658"
|
||||
y="27.882824"
|
||||
style="font-size:7.76111126px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Deliver an item to the FTC contact in Suburbia</tspan></text>
|
||||
<text
|
||||
id="text6364"
|
||||
y="37.937"
|
||||
x="152.35658"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.05555582px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="37.937"
|
||||
x="152.35658"
|
||||
id="tspan6362"
|
||||
sodipodi:role="line">Reward : Legendary SubMunition Missile Mk4</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#c57147;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="195.37274"
|
||||
y="84.18927"
|
||||
id="text6370"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6368"
|
||||
x="195.37274"
|
||||
y="84.18927"
|
||||
style="font-size:8.46666718px;fill:#c57147;fill-opacity:1;stroke-width:0.26458335px">Cannot accept more missions</tspan></text>
|
||||
<g
|
||||
id="g6485"
|
||||
transform="translate(-14.81667,12.026318)">
|
||||
<g
|
||||
transform="matrix(0.21520643,0.21520643,-0.21520643,0.21520643,286.3185,-60.540215)"
|
||||
id="g6378">
|
||||
<use
|
||||
transform="matrix(2.3233506,-2.3233506,2.3233506,2.3233506,-525.09999,803.63525)"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path6571"
|
||||
id="use6579"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<rect
|
||||
y="23.390965"
|
||||
x="351.41891"
|
||||
height="7.4835463"
|
||||
width="35.546844"
|
||||
style="fill:#8ab4e7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7229-3)"
|
||||
id="use6398"
|
||||
transform="rotate(90,370.99631,25.421645)" />
|
||||
</g>
|
||||
<text
|
||||
inkscape:transform-center-y="3.5546847"
|
||||
inkscape:transform-center-x="-0.74835467"
|
||||
id="text6396"
|
||||
y="27.506914"
|
||||
x="372.11609"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="27.506914"
|
||||
x="372.11609"
|
||||
id="tspan6394"
|
||||
sodipodi:role="line">Cancel</tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6400"
|
||||
d="m 351.98078,24.297867 v 7.276041 l 50.40313,1e-6"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#8ab4e7;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g6485"
|
||||
id="use6487"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(0,23.881537)"
|
||||
inkscape:export-filename="/tmp/export.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" />
|
||||
<g
|
||||
id="g6523"
|
||||
transform="translate(0,7.4083337)">
|
||||
<use
|
||||
style="display:inline"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path7197"
|
||||
inkscape:transform-center-y="-0.66101504"
|
||||
id="use6501"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(121.04306,-96.199953)" />
|
||||
<g
|
||||
transform="translate(0,98.954178)"
|
||||
id="g6511">
|
||||
<text
|
||||
id="text6505"
|
||||
y="27.882824"
|
||||
x="152.35658"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.76111126px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="27.882824"
|
||||
x="152.35658"
|
||||
id="tspan6503"
|
||||
sodipodi:role="line">Deliver an item to the FTC contact in Suburbia</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.05555582px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="152.35658"
|
||||
y="37.937"
|
||||
id="text6509"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6507"
|
||||
x="152.35658"
|
||||
y="37.937"
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Reward : Legendary SubMunition Missile Mk4</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g6537"
|
||||
transform="translate(0,34.925014)">
|
||||
<use
|
||||
transform="translate(121.04306,-96.199953)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use6525"
|
||||
inkscape:transform-center-y="-0.66101504"
|
||||
xlink:href="#path7197"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<g
|
||||
id="g6535"
|
||||
transform="translate(0,98.954178)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="152.35658"
|
||||
y="27.882824"
|
||||
id="text6529"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6527"
|
||||
x="152.35658"
|
||||
y="27.882824"
|
||||
style="font-size:7.76111126px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Deliver an item to the FTC contact in Suburbia</tspan></text>
|
||||
<text
|
||||
id="text6533"
|
||||
y="37.937"
|
||||
x="152.35658"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.05555582px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="37.937"
|
||||
x="152.35658"
|
||||
id="tspan6531"
|
||||
sodipodi:role="line">Reward : Legendary SubMunition Missile Mk4</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,62.441675)"
|
||||
id="g6551">
|
||||
<use
|
||||
style="display:inline"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path7197"
|
||||
inkscape:transform-center-y="-0.66101504"
|
||||
id="use6539"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(121.04306,-96.199953)" />
|
||||
<g
|
||||
transform="translate(0,98.954178)"
|
||||
id="g6549">
|
||||
<text
|
||||
id="text6543"
|
||||
y="27.882824"
|
||||
x="152.35658"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:7.76111126px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px"
|
||||
y="27.882824"
|
||||
x="152.35658"
|
||||
id="tspan6541"
|
||||
sodipodi:role="line">Deliver an item to the FTC contact in Suburbia</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.05555582px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="152.35658"
|
||||
y="37.937"
|
||||
id="text6547"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6545"
|
||||
x="152.35658"
|
||||
y="37.937"
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Reward : Legendary SubMunition Missile Mk4</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-14.81667,111.42406)"
|
||||
id="g6565"
|
||||
inkscape:export-filename="/tmp/export.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.70000076px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d2e1f3;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="371.05774"
|
||||
y="27.506914"
|
||||
id="text6561"
|
||||
inkscape:transform-center-x="-0.74835467"
|
||||
inkscape:transform-center-y="3.5546847"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6559"
|
||||
x="371.05774"
|
||||
y="27.506914"
|
||||
style="font-size:7.05555582px;fill:#d2e1f3;fill-opacity:1;stroke-width:0.26458335px">Accept</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#8ab4e7;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 351.98078,24.297867 v 7.276041 l 50.40313,1e-6"
|
||||
id="path6563"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g6608">
|
||||
<circle
|
||||
r="4.490128"
|
||||
cy="24.61265"
|
||||
cx="360.34225"
|
||||
id="path6571"
|
||||
style="fill:#222932;fill-opacity:1;fill-rule:evenodd;stroke:#8ab4e7;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#8ab4e7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1217779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path6596"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="356.96808"
|
||||
sodipodi:cy="24.61265"
|
||||
sodipodi:r1="1.918968"
|
||||
sodipodi:r2="0.01918968"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 358.88705,24.61265 -2.87846,1.661875 v -3.32375 z"
|
||||
inkscape:transform-center-x="-0.42217421"
|
||||
inkscape:transform-center-y="1.2619461e-06" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g6565"
|
||||
id="use6567"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(0,27.516676)" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g6565"
|
||||
id="use6569"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(0,55.033337)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 412 KiB |
BIN
out/assets/images/common/dialog.png
Normal file
BIN
out/assets/images/common/dialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
out/assets/images/map/mission-action.png
Normal file
BIN
out/assets/images/map/mission-action.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -8,7 +8,7 @@ module TS.SpaceTac {
|
|||
private random: RandomGenerator;
|
||||
|
||||
constructor(choices: string[], random: RandomGenerator = new RandomGenerator()) {
|
||||
this.choices = choices.slice(0);
|
||||
this.choices = acopy(choices);
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,5 +31,41 @@ module TS.SpaceTac.Specs {
|
|||
expect(shop.stock).toEqual([equ1, equ2]);
|
||||
expect(fleet.credits).toEqual(1000);
|
||||
});
|
||||
|
||||
it("generates secondary missions", function () {
|
||||
let universe = new Universe();
|
||||
universe.generate(4);
|
||||
let start = universe.getStartLocation();
|
||||
|
||||
let shop = new Shop();
|
||||
expect((<any>shop).missions.length).toBe(0);
|
||||
|
||||
let result = shop.getMissions(start, 4);
|
||||
expect(result.length).toBe(4);
|
||||
expect((<any>shop).missions.length).toBe(4);
|
||||
|
||||
let oresult = shop.getMissions(start, 4);
|
||||
expect(oresult).toEqual(result);
|
||||
|
||||
result.forEach(mission => {
|
||||
expect(mission.main).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it("assigns missions to a fleet", function () {
|
||||
let shop = new Shop();
|
||||
let player = new Player();
|
||||
let mission = new Mission(new Universe());
|
||||
(<any>shop).missions = [mission];
|
||||
|
||||
expect(shop.getMissions(new StarLocation(), 1)).toEqual([mission]);
|
||||
expect(player.missions.secondary).toEqual([]);
|
||||
|
||||
shop.acceptMission(mission, player);
|
||||
|
||||
expect((<any>shop).missions).toEqual([]);
|
||||
expect(player.missions.secondary).toEqual([mission]);
|
||||
expect(mission.fleet).toBe(player.fleet);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ module TS.SpaceTac {
|
|||
// Random generator
|
||||
private random: RandomGenerator
|
||||
|
||||
// Available missions
|
||||
private missions: Mission[] = []
|
||||
|
||||
constructor(level = 1, stock: Equipment[] = [], count = 40) {
|
||||
this.level = level;
|
||||
this.stock = stock;
|
||||
|
@ -98,5 +101,33 @@ module TS.SpaceTac {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of available secondary missions
|
||||
*/
|
||||
getMissions(around: StarLocation, max_count = 3): Mission[] {
|
||||
while (this.missions.length < max_count) {
|
||||
let generator = new MissionGenerator(around.star.universe, around.star.level, around, this.random);
|
||||
let mission = generator.generate();
|
||||
this.missions.push(mission);
|
||||
}
|
||||
|
||||
return this.missions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a mission to a fleet
|
||||
*
|
||||
* Returns true on success
|
||||
*/
|
||||
acceptMission(mission: Mission, player: Player): boolean {
|
||||
if (player.missions.secondary.length < 2 && remove(this.missions, mission)) {
|
||||
mission.fleet = player.fleet;
|
||||
add(player.missions.secondary, mission);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,10 +2,10 @@ module TS.SpaceTac.Specs {
|
|||
describe("Star", () => {
|
||||
it("lists links to other stars", () => {
|
||||
var universe = new Universe();
|
||||
universe.stars.push(new Star(universe, 0, 0));
|
||||
universe.stars.push(new Star(universe, 1, 0));
|
||||
universe.stars.push(new Star(universe, 0, 1));
|
||||
universe.stars.push(new Star(universe, 1, 1));
|
||||
universe.stars.push(new Star(universe, 0, 0, "Star A"));
|
||||
universe.stars.push(new Star(universe, 1, 0, "Star B"));
|
||||
universe.stars.push(new Star(universe, 0, 1, "Star C"));
|
||||
universe.stars.push(new Star(universe, 1, 1, "Star D"));
|
||||
universe.addLink(universe.stars[0], universe.stars[1]);
|
||||
universe.addLink(universe.stars[0], universe.stars[3]);
|
||||
|
||||
|
@ -26,6 +26,11 @@ module TS.SpaceTac.Specs {
|
|||
expect(universe.stars[3].getLinkTo(universe.stars[0])).toEqual(universe.starlinks[1]);
|
||||
expect(universe.stars[3].getLinkTo(universe.stars[1])).toBeNull();
|
||||
expect(universe.stars[3].getLinkTo(universe.stars[2])).toBeNull();
|
||||
|
||||
let neighbors = universe.stars[0].getNeighbors();
|
||||
expect(neighbors.length).toBe(2);
|
||||
expect(neighbors).toContain(universe.stars[1]);
|
||||
expect(neighbors).toContain(universe.stars[3]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -89,6 +89,14 @@ module TS.SpaceTac {
|
|||
return `Star ${this.name}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a location of interest
|
||||
*/
|
||||
addLocation(type: StarLocationType): StarLocation {
|
||||
let result = new StarLocation(this, type);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the distance to another star
|
||||
getDistanceTo(star: Star): number {
|
||||
var dx = this.x - star.x;
|
||||
|
@ -159,6 +167,13 @@ module TS.SpaceTac {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the neighboring star systems (single jump accessible)
|
||||
*/
|
||||
getNeighbors(): Star[] {
|
||||
return nna(this.getLinks().map(link => link.getPeer(this)));
|
||||
}
|
||||
|
||||
// Check if a location is far enough from all other ones
|
||||
private checkMinDistance(loc: StarLocation, others: StarLocation[]): boolean {
|
||||
return others.every((iloc: StarLocation): boolean => {
|
||||
|
|
|
@ -13,10 +13,31 @@ module TS.SpaceTac {
|
|||
radius = 5
|
||||
|
||||
// Source of randomness
|
||||
random = RandomGenerator.global;
|
||||
random = RandomGenerator.global
|
||||
|
||||
// Generates a universe, with star systems and such
|
||||
/**
|
||||
* Add a single star
|
||||
*/
|
||||
addStar(level = 1, name?: string): Star {
|
||||
let result = new Star(this, 0, 0, name || `Star ${this.stars.length + 1}`);
|
||||
result.level = level;
|
||||
this.stars.push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random universe, with star systems and locations of interest
|
||||
*
|
||||
* This will also :
|
||||
* - create a network of jump links between star systems
|
||||
* - add random shops
|
||||
* - define a progressive gradient of enemy levels
|
||||
*/
|
||||
generate(starcount = 50): void {
|
||||
if (starcount < 4) {
|
||||
starcount = 4;
|
||||
}
|
||||
|
||||
while (this.stars.length == 0 || any(this.stars, star => star.getLinks().length == 0)) {
|
||||
this.stars = this.generateStars(starcount);
|
||||
|
||||
|
@ -27,7 +48,7 @@ module TS.SpaceTac {
|
|||
this.generateWarpLocations();
|
||||
|
||||
this.stars.forEach((star: Star) => {
|
||||
star.generate();
|
||||
star.generate(this.random);
|
||||
});
|
||||
|
||||
this.setEncounterLevels();
|
||||
|
|
|
@ -30,13 +30,13 @@ module TS.SpaceTac.Specs {
|
|||
let fleet_size = fleet.ships.length;
|
||||
|
||||
checkPart(story, 0, "^Travel to Terranax galaxy$");
|
||||
(<MissionPartDialog>story.current_part).skip();
|
||||
(<MissionPartConversation>story.current_part).skip();
|
||||
|
||||
checkPart(story, 1, "^Find your contact in .*$");
|
||||
goTo(fleet, (<MissionPartGoTo>story.current_part).destination);
|
||||
|
||||
checkPart(story, 2, "^Speak with your contact");
|
||||
(<MissionPartDialog>story.current_part).skip();
|
||||
(<MissionPartConversation>story.current_part).skip();
|
||||
|
||||
checkPart(story, 3, "^Go with .* in .* system$");
|
||||
expect(fleet.ships.length).toBe(fleet_size + 1);
|
||||
|
|
|
@ -17,27 +17,27 @@ module TS.SpaceTac {
|
|||
let start_location = nn(fleet.location);
|
||||
|
||||
// Arrival
|
||||
let dialog = this.addPart(new MissionPartDialog(this, [], "Travel to Terranax galaxy"));
|
||||
dialog.addPiece(null, "Wow ! From what my sensors tell me, there is not much activity around here.");
|
||||
dialog.addPiece(null, "I remember the last time I came in this galaxy, you needed to be aware of collisions at all time, so crowded it was.");
|
||||
dialog.addPiece(null, "Well...I did not pick a signal from our contact yet. We should be looking for her in this system.");
|
||||
let conversation = this.addPart(new MissionPartConversation(this, [], "Travel to Terranax galaxy"));
|
||||
conversation.addPiece(null, "Wow ! From what my sensors tell me, there is not much activity around here.");
|
||||
conversation.addPiece(null, "I remember the last time I came in this galaxy, you needed to be aware of collisions at all time, so crowded it was.");
|
||||
conversation.addPiece(null, "Well...I did not pick a signal from our contact yet. We should be looking for her in this system.");
|
||||
|
||||
// Get in touch with our contact
|
||||
let contact_location = randomLocation(random, [start_location.star], [start_location]);
|
||||
let contact_character = new Ship(null, "Osten-37", ShipModel.getRandomModel(1, random));
|
||||
contact_character.fleet.setLocation(contact_location, true);
|
||||
this.addPart(new MissionPartGoTo(this, contact_location, `Find your contact in ${contact_location.star.name}`));
|
||||
dialog = this.addPart(new MissionPartDialog(this, [contact_character], "Speak with your contact"));
|
||||
dialog.addPiece(contact_character, "Finally, you came!");
|
||||
dialog.addPiece(contact_character, "Sorry for not broadcasting my position. As you may have encountered, this star system is not safe anymore.");
|
||||
dialog.addPiece(null, "Nothing we could not handle, we just hope the other teams have not run across more trouble.");
|
||||
dialog.addPiece(contact_character, "I do not even know if the other contacts made it to their rendezvous point. Jumping between systems has become quite a hassle around here.");
|
||||
dialog.addPiece(null, "And we still do not know why those rogue fleets are trying to lockdown the whole galaxy? Did you have some interaction with them?");
|
||||
dialog.addPiece(contact_character, "Well, they tend to shoot you on sight if you go near a location they defend. Do not know if that qualifies as interaction though...");
|
||||
dialog.addPiece(null, "So where do we go from here? In your last message, you told us of a resistance group growing.");
|
||||
dialog.addPiece(contact_character, "Yes, some merchants and miners have rallied behind a retired TSF general, but I lost contact with them weeks ago.");
|
||||
dialog.addPiece(contact_character, "We may go to their last known location, but first I want you to see something in a nearby system.");
|
||||
dialog.addPiece(null, "Ok, let's go...");
|
||||
conversation = this.addPart(new MissionPartConversation(this, [contact_character], "Speak with your contact"));
|
||||
conversation.addPiece(contact_character, "Finally, you came!");
|
||||
conversation.addPiece(contact_character, "Sorry for not broadcasting my position. As you may have encountered, this star system is not safe anymore.");
|
||||
conversation.addPiece(null, "Nothing we could not handle, we just hope the other teams have not run across more trouble.");
|
||||
conversation.addPiece(contact_character, "I do not even know if the other contacts made it to their rendezvous point. Jumping between systems has become quite a hassle around here.");
|
||||
conversation.addPiece(null, "And we still do not know why those rogue fleets are trying to lockdown the whole galaxy? Did you have some interaction with them?");
|
||||
conversation.addPiece(contact_character, "Well, they tend to shoot you on sight if you go near a location they defend. Do not know if that qualifies as interaction though...");
|
||||
conversation.addPiece(null, "So where do we go from here? In your last message, you told us of a resistance group growing.");
|
||||
conversation.addPiece(contact_character, "Yes, some merchants and miners have rallied behind a retired TSF general, but I lost contact with them weeks ago.");
|
||||
conversation.addPiece(contact_character, "We may go to their last known location, but first I want you to see something in a nearby system.");
|
||||
conversation.addPiece(null, "Ok, let's go...");
|
||||
|
||||
// Go take a look at the graveyard
|
||||
let nearby_systems = nna(start_location.star.getLinks().map(link => link.getPeer(contact_location.star)));
|
||||
|
|
|
@ -21,13 +21,17 @@ module TS.SpaceTac {
|
|||
// Indicator that the mission is completed
|
||||
completed: boolean
|
||||
|
||||
constructor(universe: Universe, fleet: Fleet, main = false) {
|
||||
// Title of this mission (should be kept short)
|
||||
title: string
|
||||
|
||||
constructor(universe: Universe, fleet = new Fleet(), main = false) {
|
||||
this.universe = universe;
|
||||
this.fleet = fleet;
|
||||
this.main = main;
|
||||
this.parts = [];
|
||||
this.completed = false;
|
||||
this.current_part = new MissionPart(this, "Empty mission");
|
||||
this.title = main ? "Main story" : "Secondary mission";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
24
src/core/missions/MissionGenerator.spec.ts
Normal file
24
src/core/missions/MissionGenerator.spec.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
module TS.SpaceTac.Specs {
|
||||
describe("MissionGenerator", () => {
|
||||
it("generates escort missions", () => {
|
||||
let universe = new Universe();
|
||||
let star1 = universe.addStar(1);
|
||||
let loc1 = star1.locations[0];
|
||||
let star2 = universe.addStar(2);
|
||||
let loc2 = star2.locations[0];
|
||||
let star3 = universe.addStar(3);
|
||||
let loc3 = star3.locations[0];
|
||||
universe.addLink(star1, star2);
|
||||
universe.addLink(star2, star3);
|
||||
|
||||
let generator = new MissionGenerator(universe, 3, loc2);
|
||||
let mission = generator.generateEscort();
|
||||
|
||||
expect(mission.title).toBe("Escort a ship to a level 3 system");
|
||||
expect(mission.parts.length).toBe(1);
|
||||
expect(mission.parts[0] instanceof MissionPartEscort).toBe(true);
|
||||
let escort = <MissionPartEscort>mission.parts[0];
|
||||
expect(escort.destination).toBe(loc3);
|
||||
});
|
||||
});
|
||||
}
|
45
src/core/missions/MissionGenerator.ts
Normal file
45
src/core/missions/MissionGenerator.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
module TS.SpaceTac {
|
||||
/**
|
||||
* Random generator of secondary missions that can be taken from
|
||||
*/
|
||||
export class MissionGenerator {
|
||||
universe: Universe
|
||||
level: number
|
||||
around: StarLocation
|
||||
random: RandomGenerator
|
||||
|
||||
constructor(universe: Universe, level: number, around: StarLocation, random = RandomGenerator.global) {
|
||||
this.universe = universe;
|
||||
this.level = level;
|
||||
this.around = around;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single mission
|
||||
*/
|
||||
generate(): Mission {
|
||||
let generators = [
|
||||
bound(this, "generateEscort")
|
||||
];
|
||||
|
||||
let generator = this.random.choice(generators);
|
||||
let result = generator();
|
||||
// TODO Add reward
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an escort mission
|
||||
*/
|
||||
generateEscort(): Mission {
|
||||
let mission = new Mission(this.universe);
|
||||
let ship = new Ship();
|
||||
let dest_star = minBy(this.around.star.getNeighbors(), star => Math.abs(star.level - this.level));
|
||||
let destination = this.random.choice(dest_star.locations);
|
||||
mission.addPart(new MissionPartEscort(mission, destination, ship));
|
||||
mission.title = `Escort a ship to a level ${dest_star.level} system`;
|
||||
return mission;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
module TS.SpaceTac.Specs {
|
||||
describe("MissionPartDialog", () => {
|
||||
it("advances through dialog", function () {
|
||||
describe("MissionPartConversation", () => {
|
||||
it("advances through conversation", function () {
|
||||
let universe = new Universe();
|
||||
let fleet = new Fleet();
|
||||
let ship1 = new Ship(null, "Tim");
|
||||
let ship2 = new Ship(null, "Ben");
|
||||
let part = new MissionPartDialog(new Mission(universe, fleet), [ship1, ship2], "Talk to Tim");
|
||||
let part = new MissionPartConversation(new Mission(universe, fleet), [ship1, ship2], "Talk to Tim");
|
||||
|
||||
expect(part.title).toEqual("Talk to Tim");
|
||||
expect(part.checkCompleted()).toBe(true, "No dialog piece");
|
||||
|
@ -36,7 +36,7 @@ module TS.SpaceTac.Specs {
|
|||
let universe = new Universe();
|
||||
let fleet = new Fleet();
|
||||
let ship = new Ship(null, "Tim");
|
||||
let part = new MissionPartDialog(new Mission(universe, fleet), [ship]);
|
||||
let part = new MissionPartConversation(new Mission(universe, fleet), [ship]);
|
||||
part.addPiece(null, "Hello !");
|
||||
part.addPiece(ship, "Hiya !");
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
module TS.SpaceTac {
|
||||
/**
|
||||
* A single dialog piece
|
||||
* A single conversation piece
|
||||
*/
|
||||
interface DialogPiece {
|
||||
interface ConversationPiece {
|
||||
// Interlocutor (null for the player's fleet)
|
||||
interlocutor: Ship | null
|
||||
|
||||
|
@ -13,14 +13,14 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
/**
|
||||
* A mission part that triggers a dialog
|
||||
* A mission part that triggers a conversation
|
||||
*/
|
||||
export class MissionPartDialog extends MissionPart {
|
||||
export class MissionPartConversation extends MissionPart {
|
||||
// Other ships with which the dialog will take place
|
||||
interlocutors: Ship[]
|
||||
|
||||
// Pieces of dialog
|
||||
pieces: DialogPiece[] = []
|
||||
pieces: ConversationPiece[] = []
|
||||
|
||||
// Current piece
|
||||
current_piece = 0
|
||||
|
@ -70,7 +70,7 @@ module TS.SpaceTac {
|
|||
/**
|
||||
* Get the current piece of dialog
|
||||
*/
|
||||
getCurrent(): DialogPiece {
|
||||
getCurrent(): ConversationPiece {
|
||||
if (this.checkCompleted()) {
|
||||
return {
|
||||
interlocutor: null,
|
||||
|
@ -88,7 +88,7 @@ module TS.SpaceTac {
|
|||
/**
|
||||
* Get the interlocutor from the player fleet that will say the piece
|
||||
*/
|
||||
private getFleetInterlocutor(piece: DialogPiece): Ship | null {
|
||||
private getFleetInterlocutor(piece: ConversationPiece): Ship | null {
|
||||
if (this.fleet.ships.length > 0) {
|
||||
// TODO Choose a ship by its personality traits
|
||||
return this.fleet.ships[0];
|
|
@ -18,6 +18,7 @@ module TS.SpaceTac.UI {
|
|||
this.loadImage("common/arrow.png");
|
||||
this.loadImage("common/button-ok.png");
|
||||
this.loadImage("common/button-cancel.png");
|
||||
this.loadImage("common/dialog.png");
|
||||
this.loadSheet("common/dialog-close.png", 92, 82);
|
||||
this.loadImage("menu/title.png");
|
||||
this.loadImage("menu/button.png");
|
||||
|
@ -70,6 +71,7 @@ module TS.SpaceTac.UI {
|
|||
this.loadImage("map/location-warp.png");
|
||||
this.loadSheet("map/status.png", 32);
|
||||
this.loadSheet("map/missions.png", 70);
|
||||
this.loadSheet("map/mission-action.png", 192, 56);
|
||||
this.loadImage("character/sheet.png");
|
||||
this.loadImage("character/close.png");
|
||||
this.loadImage("character/ship.png");
|
||||
|
|
|
@ -231,8 +231,8 @@ module TS.SpaceTac.UI {
|
|||
/**
|
||||
* Add a static image, positioning its center.
|
||||
*/
|
||||
addImage(x: number, y: number, key: string, scale = 1): void {
|
||||
let image = new Phaser.Image(this.container.game, x, y, key);
|
||||
addImage(x: number, y: number, key: string, frame = 0, scale = 1): void {
|
||||
let image = new Phaser.Image(this.container.game, x, y, key, frame);
|
||||
image.anchor.set(0.5, 0.5);
|
||||
image.scale.set(scale);
|
||||
this.addInternalChild(image);
|
||||
|
|
|
@ -7,7 +7,7 @@ module TS.SpaceTac.UI {
|
|||
* When a modal dialog opens, an overlay is displayed behind it to prevent clicking through it
|
||||
*/
|
||||
export class UIDialog extends UIComponent {
|
||||
constructor(parent: BaseView, width: number, height: number, background: string) {
|
||||
constructor(parent: BaseView, width = 1495, height = 1080, background = "common-dialog") {
|
||||
super(parent, width, height, background);
|
||||
|
||||
if (parent.dialogs_layer.children.length == 0) {
|
||||
|
@ -23,6 +23,7 @@ module TS.SpaceTac.UI {
|
|||
*/
|
||||
addOverlay(layer: Phaser.Group): void {
|
||||
let overlay = layer.game.add.button(0, 0, "common-transparent", () => null);
|
||||
overlay.input.useHandCursor = false;
|
||||
overlay.scale.set(this.view.getWidth() / overlay.width, this.view.getHeight() / overlay.height);
|
||||
layer.add(overlay);
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ module TS.SpaceTac.UI {
|
|||
/**
|
||||
* Add a close button
|
||||
*/
|
||||
addCloseButton(key: string, x: number, y: number, frame = 0, frame_hover = 1): void {
|
||||
addCloseButton(key = "common-dialog-close", x = 1325, y = 131, frame = 0, frame_hover = 1): void {
|
||||
this.addButton(x, y, () => this.close(), key, frame, frame_hover, "Close this dialog");
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ module TS.SpaceTac.UI {
|
|||
private missions: ActiveMissions
|
||||
|
||||
constructor(parent: BaseView, missions: ActiveMissions) {
|
||||
super(parent, 520, 210);
|
||||
super(parent, 520, 240);
|
||||
this.missions = missions;
|
||||
|
||||
this.update();
|
||||
|
@ -21,10 +21,11 @@ module TS.SpaceTac.UI {
|
|||
this.clearContent();
|
||||
|
||||
let active = this.missions.getCurrent();
|
||||
let offset = 245 - active.length * 70;
|
||||
let spacing = 80;
|
||||
let offset = 245 - active.length * spacing;
|
||||
active.forEach((mission, idx) => {
|
||||
this.addImage(35, offset + 70 * idx, "map-missions");
|
||||
this.addText(90, offset + 70 * idx, mission.current_part.title, "#d2e1f3", 22, false, false, 430, true);
|
||||
this.addImage(35, offset + spacing * idx, "map-missions", mission.main ? 0 : 1);
|
||||
this.addText(90, offset + spacing * idx, mission.current_part.title, "#d2e1f3", 20, false, false, 430, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ module TS.SpaceTac.UI {
|
|||
* Display of an active conversation
|
||||
*/
|
||||
export class ConversationDisplay extends UIComponent {
|
||||
dialog: MissionPartDialog | null = null
|
||||
dialog: MissionPartConversation | null = null
|
||||
player: Player
|
||||
on_end: Function | null = null
|
||||
|
||||
|
@ -21,7 +21,7 @@ module TS.SpaceTac.UI {
|
|||
*/
|
||||
updateFromMissions(missions: ActiveMissions, on_end: Function | null = null) {
|
||||
let parts = missions.getCurrent().map(mission => mission.current_part);
|
||||
this.dialog = <MissionPartDialog | null>first(parts, part => part instanceof MissionPartDialog);
|
||||
this.dialog = <MissionPartConversation | null>first(parts, part => part instanceof MissionPartConversation);
|
||||
|
||||
if (this.dialog) {
|
||||
this.on_end = on_end;
|
||||
|
|
|
@ -34,7 +34,9 @@ module TS.SpaceTac.UI {
|
|||
if (location) {
|
||||
let actions: [string, Function][] = [];
|
||||
if (location.shop) {
|
||||
let shop = location.shop;
|
||||
actions.push(["Go to dockyard", () => view.openShop()]);
|
||||
actions.push(["Show jobs", () => new MissionsDialog(view, shop, view.player)]);
|
||||
}
|
||||
|
||||
switch (location.type) {
|
||||
|
|
69
src/ui/map/MissionsDialog.ts
Normal file
69
src/ui/map/MissionsDialog.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
module TS.SpaceTac.UI {
|
||||
/**
|
||||
* Dialog to show available missions
|
||||
*/
|
||||
export class MissionsDialog extends UIDialog {
|
||||
shop: Shop
|
||||
player: Player
|
||||
location: StarLocation
|
||||
|
||||
constructor(view: BaseView, shop: Shop, player: Player) {
|
||||
super(view);
|
||||
|
||||
this.shop = shop;
|
||||
this.player = player;
|
||||
this.location = player.fleet.location || new StarLocation();
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the dialog content
|
||||
*/
|
||||
refresh() {
|
||||
this.clearContent();
|
||||
this.addCloseButton();
|
||||
|
||||
let offset = 160;
|
||||
|
||||
let active = this.player.missions.getCurrent().filter(mission => !mission.main);
|
||||
if (active.length) {
|
||||
this.addText(this.width / 2, offset, "Active jobs", "#b8d2f1", 36);
|
||||
offset += 110;
|
||||
|
||||
active.forEach(mission => {
|
||||
this.addMission(offset, mission.title, "Reward: ???", 0, () => null);
|
||||
offset += 110;
|
||||
});
|
||||
}
|
||||
|
||||
let proposed = this.shop.getMissions(this.location);
|
||||
if (proposed.length) {
|
||||
this.addText(this.width / 2, offset, "Proposed jobs", "#b8d2f1", 36);
|
||||
offset += 110;
|
||||
|
||||
proposed.forEach(mission => {
|
||||
this.addMission(offset, mission.title, "Reward: ???", 2, () => {
|
||||
this.shop.acceptMission(mission, this.player);
|
||||
this.refresh();
|
||||
});
|
||||
offset += 110;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mission text
|
||||
*/
|
||||
addMission(yoffset: number, title: string, subtitle: string, button_frame: number, button_callback: Function) {
|
||||
this.addImage(320, yoffset, "map-missions", 1);
|
||||
if (title) {
|
||||
this.addText(380, yoffset - 15, title, "#d2e1f3", 22, false, false, 620, true);
|
||||
}
|
||||
if (subtitle) {
|
||||
this.addText(380, yoffset + 22, subtitle, "#d2e1f3", 20, false, false, 620, true);
|
||||
}
|
||||
this.addButton(1120, yoffset, button_callback, "map-mission-action", button_frame, button_frame + 1);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue