From a7d8ad0004e00e1d917d636f4d69fd58f5edbfa3 Mon Sep 17 00:00:00 2001 From: celestar Date: Wed, 29 Mar 2006 16:30:26 +0000 Subject: [PATCH] (svn r4150) -Feature: Merged elrails into trunk. Thanks to Tron for lots of code and proofreading, thanks to peter1138 for another lot of code and ideas. --- BUGS | 7 + Makefile | 1 + ai/default/default.c | 45 +- bridge.h | 2 + bridge_map.h | 1 + data/elrailsw.grf | Bin 0 -> 7699 bytes docs/elrail.svg | 1091 +++++++++++++++++++++++++++++++++++++++ docs/elrail_tile.png | Bin 0 -> 64028 bytes docs/elrail_track.png | Bin 0 -> 62629 bytes docs/landscape.html | 2 +- elrail.c | 352 +++++++++++++ engine_gui.c | 7 +- gfxinit.c | 3 + lang/english.txt | 4 + misc.c | 3 - newgrf.c | 11 +- npf.c | 24 +- npf.h | 12 +- openttd.c | 69 +++ openttd.dsp | 4 + openttd.vcproj | 3 + pathfind.c | 13 +- pathfind.h | 2 +- player.h | 1 + rail.h | 22 +- rail_cmd.c | 15 +- rail_map.h | 9 +- railtypes.h | 65 ++- road_cmd.c | 1 + saveload.c | 2 +- station_cmd.c | 2 + table/elrail_data.h | 362 +++++++++++++ table/engines.h | 15 +- table/landscape_const.h | 29 -- table/sprites.h | 64 ++- train_cmd.c | 87 +++- train_gui.c | 4 +- tunnelbridge_cmd.c | 13 +- variables.h | 1 - vehicle.c | 4 + vehicle.h | 2 + vehicle_gui.c | 26 +- 42 files changed, 2258 insertions(+), 122 deletions(-) create mode 100644 BUGS create mode 100644 data/elrailsw.grf create mode 100644 docs/elrail.svg create mode 100644 docs/elrail_tile.png create mode 100644 docs/elrail_track.png create mode 100644 elrail.c create mode 100644 table/elrail_data.h diff --git a/BUGS b/BUGS new file mode 100644 index 0000000000..bcdcee6f2a --- /dev/null +++ b/BUGS @@ -0,0 +1,7 @@ +/* $Id */ + +KNOWN BUGS / PROBLEMS: + +Normal and elrail depots look the same. Use 'X' (transparent buildings) + to distinguish between them +Missing curors / icons for construction (currently using the conventional ones) diff --git a/Makefile b/Makefile index 5fb9a1eb73..4de699a2ac 100644 --- a/Makefile +++ b/Makefile @@ -630,6 +630,7 @@ SRCS += dock_gui.c SRCS += driver.c SRCS += dummy_land.c SRCS += economy.c +SRCS += elrail.c SRCS += engine.c SRCS += engine_gui.c SRCS += fileio.c diff --git a/ai/default/default.c b/ai/default/default.c index 2a638e3e90..8c4d2569e4 100644 --- a/ai/default/default.c +++ b/ai/default/default.c @@ -126,7 +126,7 @@ static void AiStateVehLoop(Player *p) p->ai.state_counter = 0; } -static EngineID AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile) +static EngineID AiChooseTrainToBuild(RailType railtype, int32 money, byte flag, TileIndex tile) { EngineID best_veh_index = INVALID_ENGINE; byte best_veh_score = 0; @@ -137,7 +137,7 @@ static EngineID AiChooseTrainToBuild(byte railtype, int32 money, byte flag, Tile const RailVehicleInfo *rvi = RailVehInfo(i); const Engine* e = GetEngine(i); - if (e->railtype != railtype || + if (!IsCompatibleRail(e->railtype, railtype) || rvi->flags & RVI_WAGON || (rvi->flags & RVI_MULTIHEAD && flag & 1) || !HASBIT(e->player_avail, _current_player) || @@ -2321,6 +2321,41 @@ static StationID AiGetStationIdByDef(TileIndex tile, int id) return GetStationIndex(TILE_ADD(tile, ToTileIndexDiff(p->tileoffs))); } +static EngineID AiFindBestWagon(CargoID cargo, RailType railtype) +{ + EngineID best_veh_index = INVALID_ENGINE; + EngineID i; + uint16 best_capacity = 0; + uint16 best_speed = 0; + uint speed; + + for (i = 0; i < NUM_TRAIN_ENGINES; i++) { + const RailVehicleInfo *rvi = RailVehInfo(i); + const Engine* e = GetEngine(i); + + if (!IsCompatibleRail(e->railtype, railtype) || + !(rvi->flags & RVI_WAGON) || + !HASBIT(e->player_avail, _current_player)) { + continue; + } + + if (rvi->cargo_type != cargo) { + continue; + } + + /* max_speed of 0 indicates no speed limit */ + speed = rvi->max_speed == 0 ? 0xFFFF : rvi->max_speed; + + if (rvi->capacity >= best_capacity && speed >= best_speed) { + best_capacity = rvi->capacity; + best_speed = best_speed; + best_veh_index = i; + } + } + + return best_veh_index; +} + static void AiStateBuildRailVeh(Player *p) { const AiDefaultBlockData *ptr; @@ -2337,10 +2372,14 @@ static void AiStateBuildRailVeh(Player *p) tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs)); + cargo = p->ai.cargo_type; for (i = 0;;) { if (p->ai.wagon_list[i] == INVALID_VEHICLE) { - veh = _cargoc.ai_railwagon[p->ai.railtype_to_use][cargo]; + veh = AiFindBestWagon(cargo, p->ai.railtype_to_use); + /* veh will return INVALID_ENGINE if no suitable wagon is available. + * We shall treat this in the same way as having no money */ + if (veh == INVALID_ENGINE) goto handle_nocash; cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE); if (CmdFailed(cost)) goto handle_nocash; p->ai.wagon_list[i] = _new_wagon_id; diff --git a/bridge.h b/bridge.h index 79ea4fbde3..18fcf81de8 100644 --- a/bridge.h +++ b/bridge.h @@ -22,4 +22,6 @@ typedef struct Bridge { extern const Bridge orig_bridge[MAX_BRIDGES]; extern Bridge _bridge[MAX_BRIDGES]; +uint GetBridgeFoundation(uint tileh, Axis axis); + #endif /* BRIDGE_H */ diff --git a/bridge_map.h b/bridge_map.h index f799077b3c..014a3671c8 100644 --- a/bridge_map.h +++ b/bridge_map.h @@ -127,6 +127,7 @@ TileIndex GetSouthernBridgeEnd(TileIndex t); */ TileIndex GetOtherBridgeEnd(TileIndex); +uint GetBridgeHeight(TileIndex t); static inline void SetClearUnderBridge(TileIndex t) { diff --git a/data/elrailsw.grf b/data/elrailsw.grf new file mode 100644 index 0000000000000000000000000000000000000000..f722d1e3a7cb97e0bf00cc7d850df488954fbfc2 GIT binary patch literal 7699 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 + + + + + + + + image/svg+xml + + + + + + + + N + + Pylon Control Point (PCP) + + + + + + + + + + + + + + + + not allowed, not owned + not allowed, owned + allowed, owned + allowed, not owned + Pylon Position Point (PPP) + + + + + + + + + + + + + + + + + + + + + + + + + + + + not allowed, but preferred (end of line marker) + not allowed + preferred, allowed + allowed + Pylon Position Point (PPP) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + preferred, allowed andcan be ignored to createlong wires (which span2 tiles) + + diff --git a/docs/elrail_tile.png b/docs/elrail_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..82407de486ef0dbc451acf766faee098bd649685 GIT binary patch literal 64028 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¬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 literal 0 HcmV?d00001 diff --git a/docs/elrail_track.png b/docs/elrail_track.png new file mode 100644 index 0000000000000000000000000000000000000000..af88bd3317920da5353412ba9516241feec4cae3 GIT binary patch literal 62629 zcmb5W2RN7i`#yZj45bn&p|nIvsf zbq@|GdnYcttM&c-c`q(5Ej%M7W&NH#dtzc@zRRZZ9=B>0T=_fSJvB2UtFEpdIeM)< z|M0WK#OdLe@g~)Q8;-SB6$}nEL|^|i5-D387)Zm&$Y^xs3e7#m+1j~s*GYrf(H15m zJR*XMf#J@H{LF{PJs0f8I*OR3|IRY+zwn5sHR}F-zleyf0m55?sc2|u1W%k0n1Ayk zDXI7Eoo)2PCfPCN{9A(M%@)(s4@r0}sb6#R^74v_jg^s;lQUa9b%(XLWU@@o$Y@t{ zreUTq*Y2B}Wa$<9A^^H1`3SPxrR6ih~L-gCOA z|NR5rg1ET2MAyl#7*WUl506_fvFd3$D?gE_>?-x3AQDf9`jwS=A1)aBsGDU(p_!qd z;!twq28E}W*Yw+Mh6!pfFW6?A9ZP)v{HAmnr=)wu`}ZlQMX(_niA- zPT#JTu6=`=fi?M1=F69~0s;c(;-xsey}jw%3v4=XpLwu9ab{rQXPC60`|Q=%*6o^Rm&lvm z-CurcCEq0i%XwHYzoNRD(qnGSO|Qf&^Nr`?7WNZ1@@bl{>=vea+idRYPIQ&tx%Taa zaog)_if7NJjsN;y{Ncm7n}LBG-UPrUqk`}XaHQMc*7w>#2Ye|?B0e22fi zl-vJ6quA5M<@iPpv6~r}N}|}`q}`8>4tn=aabbDcv_9fsB)_4GiZ7OWm!RM#M2NpW z|2C_ZZ{MnChrd;_RflXp!h1>j-!{4VG+kG*L9o=atqB}BKzqWbqayiY;;t>h;qmcd zzP`lXy?ejUW^}X9&CU5a#yox;YT1&p8=p#q$Hm=|@u%rU;N^9ERgF7tEo)%FSyf$~ zrqPItyoU?QvutTrX|T|`a%I2I1_pY1yU8v|&%b|K!j+Q38wO&;oOwSz7S~E#9{cu^ zX=Y|7JUV**6XPXmmoYYegEw@Nl9C}ij-^(utY5!=#qIE+Lp2B_LEA2gtJkhk5LX(X zgzizen|#P;`0Kth&x;o~o0ytrI}NLPZ>z_!t`8kg^ zKQ$r`^ZR$UO=t0m($V?Aj0}GLOP8|UeqWIiY^<-Z;__L!*l?I{U!>C0q$KL|=RaCB zCE^4hKK#m|`=giEH4BSpI=NT03+;BZ^6S$PMj=htZHu%I1x7`&awU{8Xr^mZ5Nt=U zZknB)<<-#SjeLdxi;?um@6mT~)|8i%qYT|~tm^f(Z&Wu5iwEAC2<<8*uh>9RC zZ@LW|Hs}{QP~&?~$;z&~EWEv=qeIYXNQG_34$b28kwW-Fs~oU2!GY=7VYRKStg;FUw1~2)sVU!r zf&$qJ*Toq#L|+2-Y{lcNL($IVx$&Qk?8Ht{2dXPquK4A2EK>O*b8;U(ykWzRqbG5+ z)boY*@26RwpR7ZuAV3)$9UYxUzOR?`m{S*>72UIkvM!8^mbmWbR{8z=)-W#V(~638 zCMG5oZ2pOfduW(A8O6m*92ze=pN|!$?)Ln>fu4au!$6KGygto+cc-Wy7Ui_HVa=wl-G10^=MbAIAy}D;b`-# zADtzxkx`w6_Iu(5L`7pmIVE+kas2xA>yVgOafc~SSV6%F%8Ie^agARGd3bsnZ$w8& zSIwnqW#+IR)=ieU;N#;H6&3a3^#o!n``5>~v_lNOZr88#L@?0Nsa#dIv9T%oW49(O zEW99W-S*m;Xnh&)o%-5qadGjGh)7KETazT`V^=@>1_TB19ri%LNExcDZ(W|Q2^IJzG$>mTa*#E2@!Y+_eiNt1Hb#py$!`kZdq)|v^MFoMUW-n`kw!Lh-^!z1!v#QUuMJ>lu;*)upud;a`+ z{X#p664%MvhG>D_$;mMMSeC6*8!zQWKev|FYCjn6IQWTUVPRnxj@6DGI{?3YU%os* z=1HG5??)o`>&P_W=_&E)k?5YGX?`A_lapPgo7veJkk}cw3sYfl1&7UMQ?d%xfr9v18|r`K#*JO^#Sh$tYCo6z`0Nz1BZ!`fiMux_ zX{$be-bB`{c%Ri^oX**iCWas;uE5O9%=+TybRB;(*Yor9FAODy8JU>)wHMf$BK5y( zXsDj*t;R`YR8UaJYtv-un9JaE+iyG_~O_+#T|qz?!9&Ub`{bmmg-}7 zT7G`MMw<_UY;K~Hfsc<5C5ryfXiMGCy0C1s2G%$3f9M^5eYkPw&K;xuGXOXh4Gjz= z&LR>JELVTzBqen1KmSlYl|vznlbX2h?%w<^e7UAZo=D0~(J~tr&5%gAZvFkD%a5aG z1J2IQy|~TagN;8cZcr}tKTzf^Wg_EY)6A2Ulp%x1Pi8dIG^a}yu|_|?0gNrq;VY@0+XYoX<4OK%0-HMP4x1uF22ik8P}C+ ze0a=K{fYlf@;9~BY9{Ha<;A``0#xm~1vVcEK@JWMm!;Wj0Xb)*4)r#8|7p_lvnG>q z!DCU!(*vuMoh2{BU!=c$z<9yiUGEztZ<(jOUb&_`NUymEjf5)#Z%@9zH!yDIonhrVCnbF%)$(?Na~Q2`mOes z?X_VVS*L}!Voz}#rO489BjT|fKh&*J7yr%s(x`t1d@ z$VlYo20xY$+)zzG@7|sUbMc!_bca#2}uJD=8Eyol5OwbzbBMhjvX}HYPZg_Tvzxr3;9NXb+3kR904A?I;u?)IC@oH1YvI ziyQ~n5%S#k5;*SNySK93-tE17Sj=TCS;ZUhdFX2r17Y-Mr0L!J_q_%7k~dGEK0WmL zsek?Pqn6F-ZFLt}q}NuC5P-ew5!pWveDA~W8S#CzDs6g2*6qh5o!#8sO?s;W=p|D) z#GHB#^xeL7EBXDe-xr=p9Mldf85`Vn@ZfsXC~AU{{WznHj12t%0zWjE`M^4Yga!B` zjT8=)+=bE1@~x+Nzh@e9VM{1g#LQ)Wcszem>bZD-?VPxXh+WjA+O8~2YrnZJ-Nk@x zz5w4^aLAp%9ULrUWp&8+YYekrWU46SMxSXOP4z|c0WJ! zU|}-4ug|2WuI?wGEYHD%6e>#=HCl#VNjWQHKXMm;Gz~b2ZrQSB6FYl@Vabd0aed2^ zmcMuSzRcCSJ z*TZ`LQgHZSs8p5y)fDg zH*t!qfy21G7j~l=L^9V;ns>BR`q9-h<37D_%X&n{W>!|s0n2x#iI?>CL;CvqEDkrm zu&B9t@80J9%1=U&6d2rBihh3o{JDqH)a>EWYwM7s(5mHh{5-^TB2_LnN5&LoDsn`N zwk3@*S-OBw5oy1(yi{UvJICdC~nW7s-V zw26Ypj%i>qvwsZ^rhQQO7wN0)77{#UKen>?d$Bx8^K+pT-X%h$oyvejvXdwMI$Ygkz|OIhKA);!Exj=0P>+|MY`3;h1_PK>UVHU zYFiLvW@i5IL^5toPfd*(*}~4j!SBu;hVEruR@X-?hZW3hY&PCgq^gbS5eW?m$?}-D zVdRq9iGxAM#5CxygrYV((aHW`|M^tAGkGU&h#yZtxaCK?Zph2a)3D+5@NtmL)X2L& zZ6ZZ{`~2A#z4*?ZJ3kjYTPDqKc70S^Tg$@#*38)WMznxol*glii-S@$sXiO))#ju! zK6sb?ozr96zJ1!6jg2kgV&Z8#SJ$AscP|7C0J(mW_S}5ut)QUbNq?FRDDWAAvI?;X z+24t@H6}tx(#DpS44`xJqD1&S((@Lx?)*bX-!~lNjIgw{G#&Y#qQNWfy>k8L&6_=_ zc(?A}J&iM`qOE-kxrTxWWa7$b4x7j+gwu3k3UnYe%YAE(!ig0%>O}kfd$9E z#EHErE&cMw&5>BUu#k_$%X@yRHbpCwlh`FL&W;l^@aw#i(mG$)84l$Mks?!-0pzWf zwLy3GhOb}0R{2s;W}y*9qtpYsgiLzr>FFwn_U%Wm^o%s69cy2px2vO3_w?-Wn6JP4 zD&yzfBZm)%#?#6~x-N={nniOS5;v?`=9iM2RKiq>grGNMzHR9Zky z3V>-`k6g!Evz3^2Ma9J_dB$bXRi)Q^+S}W&F!q}rQ1Q^Rt8+t#|NO;^)DNz}3#)5s zj*mV*JXVcV69Ae|v3Fem!9%Mljxvk4Ht$JD zOS>~RX7%B*ctJh$8+$D6qU)`ebe%-uZW4{GtuaZjWGOADp6{@0yMKQRcGkd5YCuP@*2Ec2M5 z9&PmIO`8ZpyV&WV?^nX1r{ac2YGX~!O{Sswu^;}1K7TcKE2DEO&t#HXNKieS(Zupt z-1V3F{`eENoEIL6JPkKrU0L*80(VAT>eQZZU5!JcaY5B}Vak{UpuSmy#oQo320gT} zV^3X*T0TA!WhU&_R=v(Wk%%=cyX`pId>B7&Cq8Ex%K?l(uU}3*jIM1(*an+jH(9=x z5pF&|(W#wh!Ga>%)b-uLY@j#8=jzp~dFD)mSJuj1#&@7AOYO`r=0A2UGTvg zf6BN)sPe2Pb8Q%x0G;CLyE}CztiG@;qBYsPdGn396SgLOHNmY#jt5ZZ*CR`Qd#SwV z=+UhqLfX2zGt~p#r*P6_OI*gMMw<8*78i{xd?}`8XXU-UrK+l`7LpQhu7kj)tgk<< zpkN9Vkd>1o3vl-3*(nC_r9Dk)T4cA5*AfvKl@cH)^4c$7zI+ph!*p%+FS+C{<89R7 z1-+wwQ_^l!7vYmqDVFlYa=T1+h2rf$0UFr^jR?jK8_;BJuxiiWfOhjU&Kjy5-=oqu z8M--_*JB%Q;IJCc4t;4Y^Aaz1o!l5K@0Xm+GuB#xOm*8h}>E-q(b z9#=<4IV{P-yal?3ORtukoSf`Ht9Z`5KhRoW%LO2plGSVvNDfZwm&L~s{dUwc@?t{R zgw~N<0cZ|c1n)TaJvuNWwZ+b(Tm3Zk^z_gVk_-lRMN`)Y`<)F!QmLG_#JHM}^oqO|vDN)eL$24di|6X%pmy$+4S;t0w99w$cqz<>Nv|fWt7x|jjgIaClLq`K za(!wS_ntkQw{JiA?&rWjK>6xYTGc>rR|I&i-9kc}fm?gI+U$76pLe2HB`*k|BMZoF zUW#W8*n@(Q3uHX#dQIwImUO*@uH8tr-Dh=?7L09P>$BpsH5OMnvT)Vh$BwZ)eE4uh zaAag^db$#1(w8Df^8i9O7B>&7=IFJrRL74W=l$JT>`XR>r}g!BDk&)$nVS0ZUn))@ zK}o~jefy@FFS@z89lUg4Cjp3eb7A57(8$O$)C`vVMP~$;8~`6+N$>Em&hX66TDA+1 z#R8ZQTi6W$QVTtlz}@G}iolU0eQ}~GJqeC1CpQKOLaY zuIL7`e3GDWG8AP0s`071yBsW^Xy=z?-QpjhCzJZ@;_9kZl&%Ldl~c;|*6Y_tx3aKM z@Nl%*SXk%||8#P6^q1$B!4jswdc`s$;Wk4BmL6b|2-RD=bV)g0>TPup69vJ^$r)*I z`;e&U_5#~(8lteUFgcHNaTM3^8QD~@)((NH>-NX@A7O6&{@uGx>06zKKJSJ+kjtv4 z?%JfSV(@^(joY?uBa$Y?$|p2r_8Sok#4Po6wU zppnvT|M)MUZfh4S6=+PJl{Js#G^d&9IF+!&JntxY zC-0`8!@tsse?5;se0cY63bOqT+`vu) zZV(aiGCxjzkJR5;HB!fk67qNZ&cH0CEjR&!@>+!ln`h`=W6N3QsF({Gi zC@D$C3bbf+oX^|aEK~FI3W(bHsC)M)@M6#TPFLI4uO=S=lQfN(Pu2u8vk70O0O`Mi@Vn|Rfzs^!GTSFoUgY(?Mm5r$>wa;boe}2@(oxM_4sna54P-E-hz`&UG;U$e zcIyyvl6GNCq^GCq963njugo%!D93MH3Is&y15Fi!W5m9p{!FJcM1Ym4Y9{iA z4*1XDobEbtVjEa%pe0vmTg``ca;O9h-dxY*bV{*oO4WGx;e$L170t$-+5_%Lw?bDw zu)V(ehOGg@$l$2Cnd$<@5D1icWzsX(J-j=vz!!}Es`a}h5giGCXU!REN;9l%mJ*k5tAh2P5A zu{vw}k<^ZG?9ETW3^pMXDyUgmsG%LD9@~nGiy$ufb1m*qM){Yk-MG#KcT$Zf(vgD9~!FCGi?Q^ZL^4!LhM1!OQP9 zy~fMh>M}ln9wJ-EH`k}vk-82@fE_1n4!!$5^kvUjdjS(P4HB|!9U;*IxtR|Aio{85 zFL;y<3A3Ig0p2KX(;@QivT)>h@SQu=Pb57)Bm4@Bih6OzYfvOFs;aI-fRi8wMcz*s z>{y}wPntl+?dxjUK(*ZhR!u~1_j3*X_U&7?^Qfl0g2EmF0Vcrpn(*CnJ->d{4i-V& zBDou~o2c7=PZ83lpjrJ^sd#;Ug{vGRo*)0~1-QzChz~?%{EoFph$=vDVd)xO1nCtX z8yk%K?ZaM>3q@A4m&#luTc&V#XC+=M1Vz37*DsTAFU}Ww%=15b^hnTS&Z_JQc8nCn z0Ks}EJE5jV-k3>L2+Q*R>t0h^3yiuBxtzHpcLbnzo2sg+pzDNwq??0-Ll$_uN0J__ zqN1W%xw+M7^0rPygLqk)Yq!k;KZ0M_jkO9PJ<=XLc#vchYwvR0q1mv5r?W2UZ1hx% zp${p{Vh`&Ohep?~=?wp*P@2p|G3)`WPWVE7A+=$2dxO9AOI$WU|LpmV98A&H)<*c^ zUXdqW72JnX=B8cZa+p*c!M{uo1H%`({oWtAk%JyvVAbl2V3a|AAxRji)dkZ?=hLT7 z8H4C2BL;frXRxxc6!3bUR(FF63DW#dzIFRENEQpf8>Q_hIz(^1H6dX>GT){px6H``k3apL}i2gbmp%|-i=e-t@t zA{Ol5ZPKI@)C~5~+i}b!%+w@8<7E`Ko5uGQUBJ%e^Ii zK0vAa@cDB%R5yfSxe$>KnTh2|-EC~f5vUKxq0Q5fi6u;Wn{aFh%CB;`^wFac6h=@) zF6zc-XA4=jy*{{B5EjM+;>d`IQRijpphbb?EwBbuyF#=A31|aM#Xy_D8NRHVf;Yd? z%`-vy@)JfLGW{n)#^94EE8ud8NlW94A6%IJxpExacg5NoVnw$02k)if15({!Yhupr zH|4&kXvYM0=(pSb`}bo?O2mC&op4#1MkvM&3=T514Gs+<2W{6wp2E7Gde(yL^ zL~U#Nd|PJu>OXm4&UNH_aOTgRO8*ZP6~5h9%*@{UaB5{5yt3njGO@7y>HGJH@-p10 zG0=ND&dPv6P!1I34@4F~D^DjU)FYn*Km>y9?Ch&6pheDxpV+gn4Ub9~mEVvqBR9XDH9h}IZ#@VxX zpm9zuYQEA><(y8*#t zmJ8fx`gu>>WTAe&FqlJSEM!@+| zGf*u9vp~lNAIR5~58X2x)Ia^Y0(3~nO={?pq%ZI>N0ht&xvc{ZLq^-!csD*AQvM8u zF4}^4A4Kj7li3CIgKLTBc_ZmLw|M^kc!H4-cc0~nXXWJl1bP#gWc!`FcYl2o&@ZeQ zX~}Fv(bR#g5bq66?L|t;`;gF39eH^w)AZRD+t#cb*DNhtuBz~}-idwkgtNWGRUp31 zaqz;6SFb+eV6=i&S)8q>83+-YgPez~LsB~G?S%>Ya&rF8L!WQJej!xL*6``mFaPR_ zijy+i`FWz>U$z2;dI)?DwhGW^yJ?7|=R)}K=;#srg@&Xy`c7!58Tz|(d$(jmv6XpD z1~0MDNc$36`I^Kb?JVE!Cl4M}pAO^vNMykV#83}7A$(7<25ia?fO>5k8-A=!fB$8i zE}0@YU`WyB?Af!-uh-D4o`Yboqo>Ev<~BcZsTo}ww&n-qv4vTX$->wwn9|hir5XTOx9WQ1wj%c!4gJ)OKCqTlW>Sm&%rw3z zWYhC!?d^rQBtS!HymE1nDMFGWJpq&N(HoH$NaOow=!?Je@YjGfDWBC9QAc}wV`5?Q z;3w?iCkXykKIOu-ttj2G4<0a6R)CDy_pXt804W#BSX8&P>m(mTJy?r|y<67fy%!g3 z8RrwSk*ii*WAypWQN+yfT2V2v8K!&Nmrs!Ueh6lYZh`soM+jPB!m9t>J&VU$K)wCe z&l2>#=w%kOy_U5@wDt26^v^H_6c;9}JW!Up*m~Uj(@q*+>yE;E%6D$vLI#8EExStI z2C5q3mAcelV?({hL0(=H=;j{)V8RVz6Feb`FcR#r(#ifsm1ZP<&(8LL1E^vnn#+BB zq(T|K7jbz5uk{x|xfF&KL8`|jBpd4`bWd^bg7K#x1-9|BL>;v=Ni4~(W}DVEUsd_U zQ8!u`#9&4_)kar;47|`pJj@bgO{g)+He%lvQO-GLS4h0DvU^tqAk2K{Z9103&q+f@ z^u)tGJUog|Gr&Cm>hG@syGAvC1BM{V3c#f2uf6nD4CV~@EWt$L$T|&$SLK7;!!kjU z@oYmuMWXxDV#wET2!A4Ff{V(NhY#xuH`CX9!l20L`?YJyyzz+;l4|APZH9V^ENG;3 zGuv2Lgiw`UBqmmakXmq>SO8g)krf6{gC;Kz*D;HTuTQjU+4Npt-Aq{lBM|klEgz47 z#|F_m+XOThE|6Fr#*z=!)pB-EL^?!^04W2;`~4j7nNg1)A8yUJXyRSny?5IoN5m-` zF$W)!W+788o4DgIM#>73oK+n3o5@L(t#_B?S?gX~t&?_o2P&rjyt1-6dX^8(&6>vQ zET$noLuzv}d$&bImnuY_IdjIC(1z=$NzCB?L^XC-Pn;@YYih_uB*v)ZKJaXYM9q zXR=!Rz?qa=T4~K!&IG_SiQ66_mQ$uxCl} zLARR&wKUCfxS^UeB4dIZmNPDii(@}@=n&Poz@*d?EFAUL)uZ6+))TzZmpjURr11%W zZmC%x>+9)p&7>C(T_ROG3ghQ|Ydx8VFg-jxVSAS}P2Bf_e=P{F`Z}3j@6BJo%*l4l zVykak$$Z1|g$w7-^?yT8QNi}Jd*1s};}c1Wlj9ych+>yt0wZqa zaoAo6@RNSBmqLW}%e^^B)*m;Lb>-s@()UBy8NOXP$l`Sz{!>A8Zb<9|+S@u(jn*e*5+x%A2Z+^+3$ToLx3;oz-@COYL3Ydio$5u~Z*=+PFz>K0@P2>rQZAq3kD4tEz4RU|ab88U8Hj zpc@eq0YGou+}!Aw8IbMaotcqYM605LHc?tyy6jU-3>#4a*lB$E^7Gf{Lxd{#UWL?5 z>aPp->8YJfklVNV8T527KeO7T!mfUP?rjpEW&EpGuVi)MI{>QR&3Z@U!siIMT#@7Z z2M6WA&UCogx8xa?dn-|LPvol26|eJ!b2Bf`xyYH%(gzm_h8JE}TGXbbft;KiD(l_} zXR~;FoWs@1dt$IdQJfs;_k_9%%PViD7S;{tJ^cQC?!s>Mfx-QKyoe2zB{${s=T9NJ zA}`Ep$2L-%GUCENx3p-v3&5xcM_0n>vWC=WZzeBKcoJ(}{=k`)Z`^)wt>3zB8>Pw{ z+J?lj65sZM92fiUi<#0^q8@XH{QUf;rh4U)mfwH;sPQmktV_TWHe#4aWZUIS_#lAGk4YK>Nz|;H|1Jw-loU_9E^Kz06&fJY&vNFP0QXBP+c158 zEzxREGjsQhTX4I&GvRY@$v;ziJeX?mU?y3NNxwM9i4_&>;?C8;>UGM&;Z**>4@2bqmCg?kvt@#2SkOe&dER?BV zGmv;7oX5o*mm}Z9Lyv>X4_In^^=k4=hvsZTGAb`=c?CyAQd>!BC+!B4@Vl$sWu^7S z5wA2=zEl^&MFGC4yYxsKhc*3`7)Iijx5;gE3J&%xPV zlC49xG!vkVn$XtPR=1RfUQEZpAO|N9>ZNYLI0*U_&A%wVByj=`>G^A|TjCo5Y^6T7 zv~0ss!|tqv)#k`7x^{a7!Nj&lLSiSfonLREej|fvdX;YgBHJJBGkCL;Pt8@E7Bf?y zJ>!OGQdwWG6ut`Yu3#nh$QKAhS4}Ya3oZ^QLg@VNFIsy%Q4P2`(|icz>A*a z^Or9&kW$JP`tDdrcYw$^g=QPxjW0k*7EMVT0l%OyLIP16Uw+rz%u1R7fn>>)TbYmL zy=-otw)5_)7_R>+(Ea$O2*th7|EhrFguybSd`+YO-?uR~$)bWOUe#R0)sEmqS-(sJUV-RQAs zXSnu~oE_&+qAiYWLpO349GHwQS~8c3j`ak+^g9i>GKQL8v6J3T2#maWNrxs%zjynr zm9{yjz+=mfF5om$IS^Ws=5`EM5cQe1W|MnT)ajX+m?XSc*wDYzw__G!eJvYOj$w*B zUn0o&cks>w?`+N2n7dxMeELUG?*x}As^5P<9P$<_{elw9S=kdRhEbz1Tbg$k0PZ4_Vw9>uM?Niqlb+{>` zzwE{Sqje!Syf%~@>Oa9*AT4t!h*dyvi%%K>OsJ@+60)*3;S|7 zoKzPX6-7gW$3?9m#l2OqV+&k2+627-lp84vupPO=7~h3f2??O*-Mu}2XR`S93w_b3 z=nqe6PH=*-a*f=tP~XrXhs574E)d-y1agDazR-1C9HQWF#L=h4FcP%iX&Fg$a%@2G zZ_#3>XkNlH-$a*zoehA)d}dPLkz|RXd!}_BcP3E*Dh1mKo1M~McD_tbrbG9=iAoYm zZUAy$)FB-|xY1^YK_k>*k@^1W%>4O7Z5k4vo|aCYsimc*m?P$Qt4hisyCKD>yG^EA zF3k=Tz91W>CO1$f-7qlopMk0?$9>NTK4L$QHS9r*xGO(UlN7eyB5(dYx(E4k@4t4i zG>}ZA#GBh;VRdNQQzZ^w(XeOMwL!BSFUU-gPJBb}#iY}7y?uS;g;fEukd0Tl&yBD5 zPQ&k11q4bOj03)CK%iLwWL7VmG~k?AE*X16N)2>wv?&jx{(dj>vXcAuBE8Vh?DMCQ zksPjd>ry2*NEGaC1NLCa=a6&I^>Lc|A{JBo^mrbj8E6FnXn7+62^ z^2G~bxDYD8uYin_1Pb(q=ODl2N{Qrs9gFHsk0>%6fb(e%y|^f zkD1eqzULo_T)Y-HH`(3DRo(nbkGkD^Wm>_z9sFBllwr0B^*@p@H!sf&S7rX`)2Ee1 zy<(@7UD5?q_vN{bVQWjrhLer_WZCkC;rmww49hMrtR1`CWM*sINVe_qZhHN^rKdamNy;iPI_Lyns!y^pv{@r z_x31|cljbSvk{VLBhqdikp(q;+A`X)aNn0tPbAZF3~WMehz}hdk8txjV6n(X8$=i6 zKEIXJD0$O#r-Kz}!NG=t2rDWs76uLFef}DFG#PK;*!>UQtLKO6Z5hXFcz;`Umpv|b z#d*5Cg1L(ZGYu^HkN=lA^Nx$^)(Z;;CQU?SYSjMDe^}Fl{XTkUpPf=r;QQ_fk5phw)P>9G zvl0&7!DLS^Dw>TdkqaV!Dn73zT1YJr)?@hC>D&1Y%hH{;AE{+SvDYZf4-smH0`E(z)D%Xr0 zqf+nOD_Pq`Hl=Y%_=@mvjM}%4M?C2wx9^|xak944CR7JwuNCAVI3R=c{QQ|H*ifLj z*AJX6W(!EakyI&?HQBg;Ay^EKhD{UX*P%nYuN4KY*m*b{#8Ju%i;JtiePc%G24!Xn zKuK4#X@@lzALma(^IyL(Ib#2BT*%tOb>cr!o$H~@G;N=h&sAV%-+?~4(!fA;k_j;Rdnk`M_o$gpWv5tI^{ z*kL%qWLEfBPDKPA>O%$Q4UnwBoTbu^7h^ZmCb8liW za=PKz;?mMHxb!_&@#n^9o!Q{WcmFe@F|l~q!<$4G;OVQreAx^g2OR<_`2!$FH2)kK zxebHBRPJFMA5&cB%2(CLV$Q1CeY{Y=;o~NUElBV4`1l4x!)}M}(Yv9cZ=(+Dea4uF zRom69)Y(2gR=ZwHmleY&qGPi#q-?f;G$U zeGRtGN4iXEO9c{Syw}`z(ijV;7U&z&v}G?mUmD!j3+vZ7RGWLsm5LH?PVYlT~t@U35o{l!B1!+mC&p< zBsgsmG<#rn(A2`>HXJyu5x;45Iii-G*u?!y8$JFd6>pUylh+ zR853F6UEF5cEg*UhEp7clmHsyFh<)889&9a5dy=$_o z@x{y$n^iB7?m`ELoVHO-=9vu3FVCo9`v{@2wcoCaZ@&3P6c(6gG_XK3a!P1Vbsb1y zcXD=4DF|PA$+mqv5<+r*oD5zUG5W{t)%WX`OVW2>llhK`#%E5CUC2)WN=VtbWAe;@ ze*FJqmm%LuzW@Jf+xh?I$$5Snb*8dABwN?wOsB&CnG+ zzq8C!6j0SN#q5{>#<;-w*Y#EhS(Y69@5NYz>&m!+908+sH?vGPX!>UhW>Gd_hs%cZ zBS%pTV~$(zfI_rOaSa@(kagQpBYT!-R7iF}! zufC}Ib!!rZD8aTzvXt-BlfO8=9km@raa~HL|J$52AN=*n40_dbF`EL9n7`1{uFN&} z&-Ps0{`#stBPFd%nx-iN-5zp4&D*!TC8@=<-~ZPOAjyGiBqwjqojaGRArK@K2-3C( zsRSw7&dEtWXd_3$)7=sqS~3lTP*5d9$QR<{`)5qVYLRD~iz|MFOXOb|!CobH=9TJM{$eN&W~sVor|t+k{yHZGIJ5=0 zh@2^*S|0nJLiPdF$h_`9$+yB25`XLszB7ftYX;ey}Ej_e)rXE>*U3uquFI zs3~n5>7}sg6eGV3c>13c9mxC{Hin0v|JU!j+FBFP`eY*t0}X}~??Bwcd=|x?(;>+- z+5h8)d)E$F_rDEcvdV5wv&Z)CcUOPPYc1ieuR0J2FW~9jui$RI+F5*TCkMwgJR^M& zmeN%_NqQR%r4XDmEAah#x?@bag01>%(%EUefE;7OM3J=g3Q{Mi?2`bk#0vX$CJbbd z69*tRjG;8!9yxmSCdg02d33-R5l9eEEA5;yE`pg!6MRN1hF0O5q9bCYeWV;59ka2U z=VAmY2-0y$GIN0Ym`KX_`rlikODWmvjzRE}&}ZB)c{QS9cv3_j>`+xx+sw@D4_~tk ze{}WNuUlYTNpbMPKs7BviW&6nFO&tmY@tY&dOn1%hAxcj7UfB(k_hoI04xfkTW=Ls z%8n9O(r>k*G7nw9uRf9w&#q8iT3tYYN^vr4Vga_ur*K?dOuU)70gMl6yNZ;)`ak(| zxAPOMu}i+bPLA%(Oe$vt#;1(XT#$|t47?;{UBUwpiY9PXa+oMUsi$uTgfRwWAZe=S z&#BNyP5zOB9dSEQ2tO#d0u8!|C5A&7xfTrGsi7fwS<07V3W`2~c$R;xLX5U~rU zTY_|+lQw$vWjA4Yko7hj|F6GtW&S$lpS#T28ja}r-}cFNM!AM`jTu+k1;G6@EX z_2^3glTIFDHN_yDpKBQ(9~?<2$x4(41cs?j%4=?#0JvI>m#A@&yk>kXAYZX2XOWum7gWE@^1q z(fpi(C&DnZ>&1I1HuSvx+t>(DVWgLj9GJxuA}T`$iSVc>%_MhGSYNNhlY>pi+VQs5 zvdO`(dGy$^McFPrwE%rqt)%5myD0yDh?D1B!gk-3m2h$g$22(Y#Qt96HN2+V4V1on_sQ2 zij?5?`#1(1JooO;mp^^lhbY!A6lB!Y)a&h=VH<5xPMLCf)HL97d9Mpx9uGUpHbmoD z8fArSVHEn7t($z>+n)V+eU0s%xTRn%n<*oq7&`4* zn>vde6&Ac;j->MK@?N%1vIJiyi+HTk4iVDaoV)V(ec$KZ>n^59=OpafQDDIWQ%{S@ z^EGA;uW0u_y0UF;VGRrH5ocfN{ypb0PxIZS(C_da)-RfR?ZRtzUCCNu-rkdv^&dW@ zkK4iTkZpkn@SG)X#-rFYyC^zG)sKu4pWhTozEE!QPZ_@E+@vJ`Okt?mnp!hGM!#2p z2GdqkpTsA3fi}ljY7HEDLKydXZP~IBbDiL5&ji%b_#)kzqP4;vlY@Am_kti>J;OLM z-NuczsE6Mts3$NdfzB5BoLBP5MhTB!`ux!h;|8xy-qMpI3VPy`AoWR>8>4;f2$0ht z3^7mQ3%eWLI7uFYHrgrXM29A^3IkWvC@M~qT^yttU(BbrHO~6S6G`pn+yk5&cBo$| zadLHC=^YGG{`=RGC+8~*66{#(UpmGW`ctRO&cAA@ex+yFliSF-i+AKg=v%FaKF4iO zH*opXEZf_g zy*mrnNmqJ4jg|E&@}tF^Ei}}!u`zrv@0G9Kmi+dDV&I&*M}}@d?zfj(YU*Yl@I8t- zi39~PDMY2kM`?05r!O*bc^yrE$j#UOFql~gUV?~uz7dVb;-*VJYZ_T34r2LU4+g zQ)*0e!u#!8O}dRzAz@OffeA-d9Oi9`m>r0$+hKLUcCb@w4hX@JWSTyqwtP+$2T{uq zQt6frjJ)6HZ#-a@we3vpyLHrYSaqH6ZEJQ`F2i5_nHIp*jJLxwRl4WSoS~C)&A7eC z1ee;H=J&v%md)cl9sEX&%rh`t6Dv)luCC{YW=-0Y7Xy}#XS8mZQ#yh| zeww$2D3ZLo-dEwUuDZM4MJ!!NX|c#b^N{S8)_HGlyWjHyTJfxwEhaEM zG;RIT0DN&7yRSe z=?@u7CAIx@kDX>eVR9|^%8q@%217%PW`|#91wa~iOn>#$OSHBy9(ku zzs|Z>U-QS6lojgC8nU|U=@Z@OGky?fvyH2rRu)VJA0GWdbMmjIx$qC65RT;o>nI1C zgAevJySPk=yKa=89rmA6?R!r>b+*K1lWpg1<8LpTtbEDq->^A2qQz}@>SOD(hSc1B zY1M3|wp83zIpwQWN#E6Ln0vG3*O?aWJkGsYcXY(0Yv_wJced9>E30*^hs8n`t_$_` z)$s6q_RDkLZDr;AC9yrh$7jB67Kv?nah?8)(Q#>hqMWQ z`ib3*rNVgxW_T%~?M z<4rSp$!2z{8KO_huspWOT0&I$lrqos5;|zkOX1yk>Yt`&+z<({OXj~a8%>}`lf%@9rGT8DRmbHQ9xwM>OeM! zHgzv1M*HWq`pcU)sqivc{^%ALp8xqkE#KNRq@8l(W2w-l5|`a#VoQ0Q=KNw}JIDt` z!B-7}mJ&SI-UA0(T(l!e|1l;Idf+ron>K|=SNZlWHJs$KI+(K5*Vjizd$uF&r5Gvu zV+Z zzkF=7WhkjUWnjJr4|c2g@nbtcHrW`DXZ?3oN&}V7lQ>1_OE*^?%|`i8J(Wt%I-H!h zrlwBH<6&hj>6IP%)BM;0^8ijJEkC9@PZm=GfiLH&Bi@rreMxVHZ%e6$0S&(~{>b%m-`2T`^OJnq~`To-ZJD-%LjX84hP&+R8E zVlarLs13Has-t5k1}0BgS*0t*1H&Z3`%vgQ$%z?j^baHh4?CC4RYy2C$;k*j2LRhl z4QhlQR;U#i)0Ipi-jG~4;fv3a+5Z54laI=fjl+YJ$mhacZOz(^M@5mNykOgUQS%kt z-HX3oCoAr`{ncav2H+$+K8XH)kR>rB7!1$^`!=4>w+mzi+M`W<-9?Ts1ux(cJ&;lM z>WATRI~BNe(ks|DdL0juAn8Y#w87)tgg^euhnR~=XMU42>L3-Lf*AgH*(Yo_;xP)I ziv!UbITb&^tbB%sPkM0>XTTifYc_I9B!9O7i-u@yEwoQmT?DtY`@wr73yahl>W{#6 zUsj=N7X{J`W2UJ%FGm>DVIb86DB#+*?brc#Z|{|W-bxXX z1nq$q)RQ=9J|g0bDoH+@{W0?R8VEiN5wHM-j5zi)xRZH_=NYECav(Zx15B)}^!Sv3 zz0V_=p!ds5J`w^5?Bn@C>lo=&uR{dw1-?Ao;m%P8ID=SJ0pg`!`69~0%XNeer3aV5)afrn~5vYmk(k=KSb|ThQ^tZWruTC z)?Qj#TGB>@qZ4G7xb^QHZQkUeZ!y-gw|-_wl2$p_Np6S1e5VEb-#>r2s0Q$8w!AWR0wx+=_0TNPLtS zWPO3@j*}hqv{IzsjGuw2gMr%V^m{f{H&>ckP9^K+szjf$v`kkT>ghR-qe{>meARLA zz%W<_)=jw?0D_GqETiBJkP@z1J1U|6Qtv14Iehau4VGCbtu9ut^Qfp1t^jq< z#LiB*snSoMRO3(MB{i`BvlJ`SRp1*=Cz8+h?*02e)qG+6S+}r}Afi#OC!XO(;vf_% zhG4WQXCQ`}CSPIb#3_VhS2kx;3T$xqundS-9+HWNN~G0`DM!IhLjlW?Lo5kl#<~= zw|iZ^bb&T1nua;2%NW>hpEIJ{8XoTlK?g;+98P}~6@8rce0T(D|yn&FS9fha~ zItzC!=5Xw$z%S&mivr6{y)HqyW-V>-laH3RO3C>UU3k@#?Z4G; zt8^iR$5H*KzKfq_m#S_oYoPJv+zb+)3@pC_d$xjMSyDKd|x zro?d|d+sxD`3{o@+UDa33jlErtuJ!JR)D&NY6#dwICM`CQ^*@a(L`(Wia$IsFtAeO z@wh~C0=oRg(%NoM+`GhA+1c*pP78r{oGzD}K29uXil?rucv)Ht?P59H{m?2#2L0wr z0VPOFsfz|SL#M#Y%L~4G{qF#c?2*bLn8G1X`C4GRzQU|%v%pXgL$q>%1c&|b(fAw8 z(an!iGPSS)(^80SQW2a$<}+?NF}ngXEuC2?R>JOg6ldDnwQIx2ZLKJ>(4CF<2#Q4< zc$H_p6CPkKttWC_1jj?Kamen^&uvVNDm*vBTHHfeZ{IE({c-aBalf~9Grh{*^9#wb zf?Yudj!ds!s!T#B1CaS4Apnm&0K!4?3rLBUK$A_a`aK>5)$s6Z&vWki%+HMc*L^M&{k;7X#I3A+nNZhgw?WRQ5I{N6d3?BH{eXHL|707ttsBH<6V|GJ>hWl zhIZpTc3L9iAp9FqbpZT-BH?fdihZ%7{281O5vXq$Q(<5YfKR6jN~!}E-zkH2q8jlwb{}mP=w(079hw;<_vzY8!AF*cw8kU=O?!z{z?S(i9L*C z#0vX4MGsL}6DqMr?T9vk%B2h?`CiY<0JX8@DAM0f*!Rl1l|5 zM^oD`D!w_F}!E9*U8H_{8retiXmeDZ;xudKVM+mGsX0(aqN6?NGOoE zYayzvt6y^>>W>>3gh9Ymvw8oKBhPP7{8mJlW_k+mGyA?PY!y{ijOK4!VxN2PBU~ls zRIoHe&GLp&fb~Pj8gjr=+9a_#mMj~yDwSWVZ8-ZyyVfu;a6zydI62UmcpPPT6sX4N zaok0ep|KlUkxX+2H%uk}%oMD<%P9wxqL(WF6hMf12OF}*%KI|XI2vQ&KwC>am2@gn znHl+|dRitEd8iqjK>>^6>01f|IxkMBQzL|IMbWq1$?I^l02 z5W~$`h16_8@q33*gA<)Cbci58)qn0idFIS@V%Qz^h(f|HXWSlo{4*}8st@ZJk4gxPO{vfSDM6$>i2N^p2*}s|q zL;wBp&j0@C?orVjy3I(l>P&>eriNWUlim669UJb4mO(vk;8-)HxY{^f!3MoFEx z!|rtSS2?*lzGOYF4%HiYWqxUL)|$iQ^53v?}PRi0!^||4y6` z58dXa`V@3LeSL?SAo$uqR4d$>O&@YB6PZ}{(MuHuy>gfw7T=*|u^tUaBgf(`?%zRB zv0r<~Kb<)YC4n84DfW9k`=OIL?GL4CUpk{hb zj%RXA=o6C%MA2+17RbuR=J8NsdO51;tSyN1pY*Hr7mtS!q7e=S9)WiwooBJH56+S>Il*f(KS+#_^j zBw3Z1>0mTYRJ~6GJHRFkB8qZz2Q4~fOqh?8UZ*jIHCww|u~=R+C2AIx9q6b8RSwsh zNKm?REW(H|+ltzd)L_vg=(GrEhu*bu>oG+jQAjjqgj3`4Vc6msVV55r`y|w$sUWoK z@nbpl&B_%5>qbDAP(-L}3Eo@hLBA7Dtccj4v!!ht(=r3pO^=WjZg<0^IH~mgv(f{0 zH$|>r@BEn7LHFdz#jY~9O8#B1?x^*zHfTS%*2}SumFH*x}a7AM)I7YDt4Tj_NI3`*a~mo zNSY2O4{2PUf3JY>u3ZQmvp#>dXd|i)srVG*T7F77$4PQ6Bg^v&dX6NQLWjTo4`71U zI;eg2t>vK3)Qq-v^fAHYxr#P*L2R3EO$e zo7U(M-PQ?-D|eft9Rn($qo#`Ij5S?{iVl0t&CqxJ={l~?u7#owdn_>5IAs$5jDI-A z3ooed-HXtZyKwmtAI`(A>Vs2)l|)zsJOz7dg1!9>B3S~&hS)HvT|vc}4)9$dYYh)d znXXQxQtkz|!1TO1J(L!|TP%*|H;0fa9z66UAntLEBY9K;3;WQ-Imi|NGpIr#VYZ{hYLUO;tt zys{7{qpQ9H&37sK4g@`vK}#WcqpjrS#aW!T?lAn5PMLs@(BcvUq6>YEfhWvY6vPYi z94a*DP*&iVkc=A@TX^`fGAkcyIy&H(LR6<18ZjT?#g!A~H` zs5o{Atqenx`t* z%(*A-+0l`Xe&0Lg^FLlAJN}dbqT`R6^m5yeYd@`YF)^hnzqjO=+P4j7Om&cH2k9bCZ|{ODZyXf4k>*_K?r`8fa9oBmZ2ho;nEOEGhjD&lM)Pv zy=HF#4N={Ys*K#?GZIrva9spCBpEG$CJDKUKcSp)jh!g%ax6M%r^g2wDZ~twfWG!c za5Cx$L7y#a*E$2p1FEXc|F*gs!Ag9v924Oxav@lO$&>gZ)Vc1U9KNFx{#bu|-_n=p zwyqV9u|N_f3GDWJ;Y8ap&=6?xMNHP7$-S7Aa<;(c$X0Qk2glsM`UW-@Hr!lylIMu{ zLM4aOsnpV5wL(vZT(rI%ocnGboS#3;5+8ppu;ujG!&|@QUqdr-Dyg)Wyzm-)b&PmD z`rZXk%eY!C>^S@L@Bcw)02<{_o>WfwJ3h`!T?d~Wu|q)MJ~T~z{rxJC(W}hBF5*Th zq00!YfwScV#V;a~uA6?z$VdgKnEVtU&)B=k9t(dbw6Q136+lzogBe?C@6}YJ%$jZIl!De`)=J&T) zfN~X4v9}&O@1XT?wy&?tJ+*qZP;XDztP!Y2qfPH_0k1`_;GqB@p_nV+k+SVp8FMpxw1A zm|1=}D@(y?URM=D>?{jSt@90W#zItkj^#0ad<+fJD+g;OR!ox$wa+4kIh1gD370umb{1D2_wd2Y<_!SFve1^~l z+6*LT>sKHCA>7|yyeUQRnft>0%h&bM?jq;Q*xx-Jqdy%|Q|`0L5D9DUsqa2)CnsK_ zzTl^(J)#%zidQWARG%>Ww*pddRe_gjX%uzQXnyD|t?b>ltjn5vElncu5k0)Tj-k+n zqD^RvCI}c}(Iwg=05|}_sL-AE8qm$-$@|2V6`!!&ieyXG_&so&y139Gl$?kepg_Z2 zyFT!F6_FvKnum&&=p~3M1-DujRRR-=65wE+IIf8R6z{j22(wovtSTgG-psHb_W#@W z7Vy_3;Ij2qviw=a&}w7v#w`el0_3m?NU&;a1ix*_I;*A7mm3@N9XNcrut0v zVJmc1R8(E?WNt*nPAh8~hq;k8au;>_oC%t!5@YkAASz0RUqQic{9Qg~pR`zR=!SPS z@PR4N8|dHez&{4M0w~}bF_VuJ%nVpgRiIH^c?t_Q^h8W{cF2M@L1MM$p*3(EK1ZS& z5|oJMJw-S7?itBBwKyU_2SDa}_$QQD>!x}6_~3htNEtjHqiP%ezPfs2(5^3mcHyo| z%%42HndJFItRCVrsx~ID*u%qujOc+d@TJl&M9Lp&tjZWwe&7i@c=y4>o&UBNqy zMMbo@NW*2X=!L-rv>jTx_y*)@ssHuA#R&DCwA$&uwuNPb++ z5muWhmXkqj2sjjo%oxW`(+%RSUT8!1$+bM~wu2Fbu6bR6I~VV^c1u~}>2Fvg5} z8Ic1-Ssg6_Xpo*Fsqr{dwi5)E*k|8$5%nMTQlyiXBE6afT##=@Nl*bjavfL)`4Eyr zN2n-Q*dZW{CMPzTJpznp2LcphVqzw7h^kKuJQ@UCalSu~5ZD;@#xpzNg~AD$PxMJT zSt|e$+$%1YB*|(3r_MvN2*RooCQpIPFt~YO)gr-!1v9_%NqR4F{vt?9-btX8&F=4i zPj&ox{kS|%_z3mH%K8c~Q9*NqkslX7PPFHLY)mv3EZqO>Lf8oF#AZJ3L$)J4G~qB5 z#Wn2IFL(lRaB3#KKByM~pml?mj&oz0Y&`GRG4jf%XE3v}3e6QF z@9d1ZyPENRj~e}F^RrVfIhKaZqobW4GrH-XJgs43Z&_<<`k9}<*ZKZ>r#q0ZW(YF~ zzJS&rH8KgX#NLX4SFN2@_ffTD`VF?;?-=-WbMHtEQJI4rBSE~^t{H4Un_GAa^e99RJNHK17`;W50Dn659KO!X((b)Ol7up?M)R(9q{I@4nij@;kBVDj! z@!Kk&{QURjm;U#2IsSe5e_L2(&BI0AN?_%`FW0JA?Cg_N{`>O81OL99?Z3Az@ZV2g z(c!uXmP9X}C+n4W%BuWpvXj34?;F{l6DUlG^}owX_y?qj{qOfQc9J&!iQNCb{PyCP z+X?*d%c~Up$vlf+vzPcjKQQpha`=29c}6E`OD@ZRaZ1&oN9$fDL!ZOwU`PNhQ8gf# z8W{n%u|iDoz)5T@_AlkGs(I8IBpnl>A&i%RU6H>*&8tZSHK6qjF^&spY22WaScYYn z9N7cGsK*Z~X>Ix6rH<9@N*t*S+;m`m%F=t`){#?hemF4)QMBiKUWFX!vRl?w%&{hY zaxAA0lJN`gp6+D?An1(E63i!RL6maxb`Wzzli-2h+ccS88z%V>u^b2pVY~!HguK;o z&zT(w?ccC&-CZoQPT=_Dg4VIH+{6D~z#f*hWkq7-|L&E3G;cTk=dBbAWgt1NV_vwN zd-BNe(atmXpKu)Eu$~X5GanSSp4BWPAUWam&~-qSo3&*%I$-wy-Qcj6*4F!f?w`

h@PDk_Sc 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 literal 0 HcmV?d00001 diff --git a/docs/landscape.html b/docs/landscape.html index 92fed219e4..b28a8932fc 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -129,7 +129,7 @@ m5 bit 7 clear: railway track B  fence on the N side (track in the S corner) C  on snow or desert -

  • m3 bits 0..3 = track type: 0 - conventional railway, 1 - monorail, 2 - maglev +
  • m3 bits 0..3 = track type: 0 - conventional railway, 1 - electrified railway, 2 - monorail, 3 - maglev m5 bits 7 and 6 set: railway depot / checkpoints
      diff --git a/elrail.c b/elrail.c new file mode 100644 index 0000000000..cfe69b2ab7 --- /dev/null +++ b/elrail.c @@ -0,0 +1,352 @@ +/* $Id$ */ +/** @file elrail.c + * This file deals with displaying wires and pylons for electric railway systems. +

      Basics

      + +

      Tile Types

      + +We have two different types of tiles in the drawing code: +Normal Railway Tiles (NRTs) which can have more than one track on it, and +Special Railways tiles (SRTs) which have only one track (like crossings, depots +stations, etc). + +

      Location Categories

      + +All tiles are categorized into three location groups (TLG): +Group 0: Tiles with both an even X coordinate and an even Y coordinate +Group 1: Tiles with an even X and an odd Y coordinate +Group 2: Tiles with an odd X and an even Y coordinate +Group 3: Tiles with both an odd X and Y coordnate. + +

      Pylon Points

      +

      Control Points

      +A Pylon Control Point (PCP) is a position where a wire (or rather two) +is mounted onto a pylon. +Each NRT does contain 4 PCPs which are mapped to a byte +variable and are represented by the DiagDirection enum: + +A wire that ends on the PCP has a dark ending, otherwise the end is bright.

      + +Now on each edge there are two PCPs: One from each adjacent tile. Both PCPs are merged +using an OR matrix (i. e. if one tile needs a PCP at the postion in question, both +tiles get it). + +

      Position Points

      +A Pylon Position Point (PPP) is a position where a pylon is located on the ground. +Each PCP owns 8 in (45 degree steps) PPPs that are located around it. PPPs are numbered +0 to 7 with 0 starting north and numbering in clockwise direction. Each track bit has PPPs +that are impossible (because the pylon would be situated on the track), preferred (because +the pylon would be rectangular to the track). PPPs are represented by the Direction enum. + + + + + */ + +#include "stdafx.h" +#include "openttd.h" +#include "tile.h" +#include "viewport.h" +#include "functions.h" /* We should REALLY get rid of this goddamn file, as it is butt-ugly */ +#include "variables.h" /* ... same here */ +#include "rail.h" +#include "debug.h" +#include "tunnel_map.h" +#include "road_map.h" +#include "bridge_map.h" +#include "bridge.h" +#include "rail_map.h" +#include "table/sprites.h" +#include "table/elrail_data.h" + +static inline TLG GetTLG(TileIndex t) +{ + return (HASBIT(TileX(t), 0) << 1) + HASBIT(TileY(t), 0); +} + +/** Finds which Rail Bits are present on a given tile. For bridge tiles, + * returns track bits under the bridge + */ +static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override) +{ + switch (GetTileType(t)) { + case MP_RAILWAY: + if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0; + switch (GetRailTileType(t)) { + case RAIL_TYPE_NORMAL: case RAIL_TYPE_SIGNALS: + return GetTrackBits(t); + default: + return 0; + } + break; + case MP_TUNNELBRIDGE: + if (IsTunnel(t)) { + if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0; + if (override != NULL) *override = 1 << GetTunnelDirection(t); + return (_m[t].m5 & 1) ? TRACK_BIT_Y : TRACK_BIT_X; + } else { + if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0; + if ( + IsBridgeMiddle(t) && + IsTransportUnderBridge(t) && + GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL) { + return GetRailBitsUnderBridge(t); + } else { + if (override != NULL && DistanceMax(t, GetOtherBridgeEnd(t)) > 1) *override = 1 << GetBridgeRampDirection(t); + + return GetBridgeAxis(t) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y; + } + } + case MP_STREET: + if ((_m[t].m4 & 0xF) != RAILTYPE_ELECTRIC) return 0; + return GetCrossingRailBits(t); + case MP_STATION: + if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0; + return _m[t].m5 & 1 ? TRACK_BIT_Y : TRACK_BIT_X; + default: + return 0; + } +} + +/** Draws wires and, if required, pylons on a given tile + * @param ti The Tileinfo to draw the tile for + * @todo Currently, each pylon is drawn twice (once for each neighbouring tiles use OwnedPPPonPCP for this) + */ +static void DrawCatenaryRailway(const TileInfo *ti) +{ + /* Pylons are placed on a tile edge, so we need to take into account + the track configuration of 2 adjacent tiles. trackconfig[0] stores the + current tile (home tile) while [1] holds the neighbour */ + TrackBits trackconfig[TS_END]; + bool isflat[TS_END]; + /* Note that ti->tileh has already been adjusted for Foundations */ + uint tileh[TS_END] = {ti->tileh, 0}; + + TLG tlg = GetTLG(ti->tile); + byte PCPstatus = 0; + byte OverridePCP = 0; + byte PPPpreferred[DIAGDIR_END] = {0xFF, 0xFF, 0xFF, 0xFF}; + byte PPPallowed[DIAGDIR_END] = {AllowedPPPonPCP[0], AllowedPPPonPCP[1], AllowedPPPonPCP[2], AllowedPPPonPCP[3]}; + byte PPPbuffer[DIAGDIR_END]; + DiagDirection i; + Track t; + + /* Find which rail bits are present, and select the override points. + We don't draw a pylon: + 1) INSIDE a tunnel (we wouldn't see it anyway) + 2) on the "far" end of a bridge head (the one that connects to bridge middle), + because that one is drawn on the bridge. Exception is for length 0 bridges + which have no middle tiles */ + trackconfig[TS_HOME] = GetRailTrackBitsUniversal(ti->tile, &OverridePCP); + /* If a track bit is present that is not in the main direction, the track is level */ + isflat[TS_HOME] = trackconfig[TS_HOME] & (TRACK_BIT_UPPER | TRACK_BIT_LOWER | TRACK_BIT_LEFT | TRACK_BIT_RIGHT); + + if (IsTunnelTile(ti->tile)) tileh[TS_HOME] = 0; + if (IsBridgeTile(ti->tile) && IsBridgeRamp(ti->tile)) { + if (tileh[TS_HOME] != 0) { + tileh[TS_HOME] = 0; + } else { + switch (GetBridgeRampDirection(ti->tile)) { + case DIAGDIR_NE: tileh[TS_HOME] = 12; break; + case DIAGDIR_SE: tileh[TS_HOME] = 6; break; + case DIAGDIR_SW: tileh[TS_HOME] = 3; break; + case DIAGDIR_NW: tileh[TS_HOME] = 9; break; + default: break; + } + } + } + + for (i = DIAGDIR_NE; i < DIAGDIR_END; i++) { + extern const TileIndexDiffC _tileoffs_by_dir[]; + TileIndex neighbour = ti->tile + TileOffsByDir(i); + uint foundation = 0; + int k; + + /* Here's one of the main headaches. GetTileSlope does not correct for possibly + existing foundataions, so we do have to do that manually later on.*/ + tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL); + trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL); + isflat[TS_NEIGHBOUR] = trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_UPPER | TRACK_BIT_LOWER | TRACK_BIT_LEFT | TRACK_BIT_RIGHT); + + /* We cycle through all the existing tracks at a PCP and see what + PPPs we want to have, or may not have at all */ + for (k = 0; k < TRACKS_AT_PCP; k++) { + /* Next to us, we have a bridge head, don't worry about that one, if it shows away from us */ + if ( + trackorigin[i][k] == TS_NEIGHBOUR && + IsBridgeTile(neighbour) && IsBridgeRamp(neighbour) && + GetBridgeRampDirection(neighbour) == ReverseDiagDir(i) + ) continue; + + if (HASBIT(trackconfig[trackorigin[i][k]], PPPtracks[i][k])) { + DiagDirection PCPpos = (trackorigin[i][k] == 0) ? i : ReverseDiagDir(i); + PCPstatus |= 1 << i; /* This PCP is in use */ + PPPpreferred[i] &= PreferredPPPofTrackBitAtPCP[PPPtracks[i][k]][PCPpos]; + PPPallowed[i] &= ~DisallowedPPPofTrackBitAtPCP[PPPtracks[i][k]][PCPpos]; + } + } + + /* Deactivate all PPPs if PCP is not used */ + PPPpreferred[i] *= HASBIT(PCPstatus, i); + PPPallowed[i] *= HASBIT(PCPstatus, i); + + /* Station on a non-flat tile means foundation. add one height level and adjust tileh */ + if (IsTileType(neighbour, MP_STATION) && tileh[TS_NEIGHBOUR] != 0) tileh[TS_NEIGHBOUR] = 0; + + /* Read the foundataions if they are present, and adjust the tileh */ + if (IsTileType(neighbour, MP_RAILWAY)) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]); + if (IsBridgeTile(neighbour) && IsBridgeRamp(neighbour)) foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], GetBridgeAxis(neighbour)); + if (foundation != 0) { + if (foundation < 15) { + tileh[TS_NEIGHBOUR] = 0; + } else { + tileh[TS_NEIGHBOUR] = _inclined_tileh[foundation - 15]; + } + } + + /* Convert the real tileh into a pseudo-tileh for the track */ + if (IsTunnelTile(neighbour)) tileh[TS_NEIGHBOUR] = 0; + if (IsBridgeTile(neighbour) && IsBridgeRamp(neighbour)) { + if (tileh[TS_NEIGHBOUR] != 0) { + tileh[TS_NEIGHBOUR] = 0; + } else { + switch (GetBridgeRampDirection(neighbour)) { + case DIAGDIR_NE: tileh[TS_NEIGHBOUR] = 12; break; + case DIAGDIR_SE: tileh[TS_NEIGHBOUR] = 6; break; + case DIAGDIR_SW: tileh[TS_NEIGHBOUR] = 3; break; + case DIAGDIR_NW: tileh[TS_NEIGHBOUR] = 9; break; + default: break; + } + } + } + + /* If we have a straight (and level) track, we want a pylon only every 2 tiles + Delete the PCP if this is the case. */ + /* Level means that the slope is the same, or the track is flat */ + if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) { + for (k = 0; k < NUM_IGNORE_GROUPS; k++) + if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) PCPstatus &= ~(1 << i); + } + + /* Now decide where we draw our tiles. First try the preferred PPPs, but they may not exist. + In that case, we try the any of the allowed ones. if they don't exist either, don't draw + anything */ + if (PPPpreferred[i] != 0) { + /* Some of the preferred PPPs (the ones in direct extension of the track bit) + have been used as an "end of line" marker. As these are not ALLOWED, this operation + cancles them out */ + PPPbuffer[i] = PPPpreferred[i] & PPPallowed[i]; + /* We haven't any buffer yet, so try something else. Fixes 90° curves */ + if (PPPbuffer[i] == 0) PPPbuffer[i] = PPPallowed[i]; + } else { + PPPbuffer[i] = PPPallowed[i]; + } + + if (PPPbuffer[i] != 0 && HASBIT(PCPstatus, i) && !HASBIT(OverridePCP, i)) { + for (k = 0; k < DIR_END; k++) { + byte temp = PPPorder[i][GetTLG(ti->tile)][k]; + if (HASBIT(PPPbuffer[i], temp)) { + uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp]; + uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp]; + + /* Don't build the pylon if it would be outside the tile */ + if (!HASBIT(OwnedPPPonPCP[i], temp)) { + /* We have a neighour that will draw it, bail out */ + if (trackconfig[TS_NEIGHBOUR] != 0) break; + continue; /* No neighbour, go looking for a better position */ + } + + AddSortableSpriteToDraw(pylons_normal[temp], x, y, 1, 1, 10, + GetSlopeZ(ti->x + x_pcp_offsets[i], ti->y + y_pcp_offsets[i])); + break; /* We already have drawn a pylon, bail out */ + } + } + } + } + + /* Drawing of pylons is finished, now draw the wires */ + for (t = 0; t < TRACK_END; t++) { + if (HASBIT(trackconfig[TS_HOME], t)) { + + byte PCPconfig = HASBIT(PCPstatus, PCPpositions[t][0]) + + (HASBIT(PCPstatus, PCPpositions[t][1]) << 1); + + const SortableSpriteStruct *sss; + int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; /* tileh for the slopes, 0 otherwise */ + + if ( /* We are not drawing a wire under a low bridge */ + IsBridgeTile(ti->tile) && + IsBridgeMiddle(ti->tile) && + !(_display_opt & DO_TRANS_BUILDINGS) && + GetBridgeHeight(t) <= TilePixelHeight(t) + ) return; + + assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */ + assert(!IsSteepTileh(tileh[TS_HOME])); + sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]]; + + AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset, + sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + min(sss->x_offset, 15), ti->y + min(sss->y_offset, 15)) + sss->z_offset); + } + } +} + +static void DrawCatenaryOnBridge(const TileInfo *ti) +{ + TileIndex start = GetOtherBridgeEnd(GetSouthernBridgeEnd(ti->tile)); + uint length = GetBridgeLength(GetSouthernBridgeEnd(ti->tile), GetOtherBridgeEnd(GetSouthernBridgeEnd(ti->tile))); + uint num = DistanceMax(ti->tile, start); + const SortableSpriteStruct *sss; + Axis axis = GetBridgeAxis(ti->tile); + TLG tlg = GetTLG(ti->tile); + + CatenarySprite offset = axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH; + + if ((length % 2) && num == length) { + sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset]; + } else { + sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset]; + } + + if (num % 2) { + if (axis == AXIS_X) { + AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + 8); + } else { + AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, GetBridgeHeight(ti->tile) + 8); + } + } + + if (DistanceMax(ti->tile, start) == length) { /* need a pylon here (the southern end) */ + if (axis == AXIS_X) { + AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + 8); + } else { + AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, GetBridgeHeight(ti->tile) + 8); + } + } + + AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset, + sss->x_size, sss->y_size, sss->z_size, GetBridgeHeight(ti->tile) + sss->z_offset + 8); +} + +void DrawCatenary(const TileInfo *ti) +{ + switch (GetTileType(ti->tile)) { + case MP_RAILWAY: + if (GetRailTileType(ti->tile) == RAIL_TYPE_DEPOT_WAYPOINT && GetRailTileSubtype(ti->tile) == RAIL_SUBTYPE_DEPOT) { + const SortableSpriteStruct *sss = &CatenarySpriteData[WIRE_DEPOT_SW + ReverseDiagDir(GetRailDepotDirection(ti->tile))]; + AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset, + sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x, ti->y) + sss->z_offset); + return; + } + /* Fall through */ + case MP_TUNNELBRIDGE: + if (IsBridgeTile(ti->tile) && IsBridgeMiddle(ti->tile) && GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenaryOnBridge(ti); + /* Fall further */ + case MP_STREET: case MP_STATION: + DrawCatenaryRailway(ti); + break; + default: + break; + } +} + diff --git a/engine_gui.c b/engine_gui.c index 61147d644e..69df50f427 100644 --- a/engine_gui.c +++ b/engine_gui.c @@ -20,9 +20,10 @@ static StringID GetEngineCategoryName(EngineID engine) { if (engine < NUM_TRAIN_ENGINES) { switch (GetEngine(engine)->railtype) { - case RAILTYPE_RAIL: return STR_8102_RAILROAD_LOCOMOTIVE; - case RAILTYPE_MONO: return STR_8106_MONORAIL_LOCOMOTIVE; - case RAILTYPE_MAGLEV: return STR_8107_MAGLEV_LOCOMOTIVE; + case RAILTYPE_RAIL: return STR_8102_RAILROAD_LOCOMOTIVE; + case RAILTYPE_ELECTRIC: return STR_8102_RAILROAD_LOCOMOTIVE; + case RAILTYPE_MONO: return STR_8106_MONORAIL_LOCOMOTIVE; + case RAILTYPE_MAGLEV: return STR_8107_MAGLEV_LOCOMOTIVE; } } diff --git a/gfxinit.c b/gfxinit.c index 78c2367a3e..0d31c71236 100644 --- a/gfxinit.c +++ b/gfxinit.c @@ -358,6 +358,9 @@ static void LoadSpriteTables(void) load_index = SPR_AUTORAIL_BASE; load_index += LoadGrfFile("autorail.grf", load_index, i++); + assert(load_index == SPR_ELRAIL_BASE); + load_index += LoadGrfFile("elrailsw.grf", load_index, i++); + assert(load_index == SPR_2CCMAP_BASE); load_index += LoadGrfFile("2ccmap.grf", load_index, i++); diff --git a/lang/english.txt b/lang/english.txt index 7b7c1bf4a0..e2dee014b3 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -1443,6 +1443,7 @@ STR_1005_NO_SUITABLE_RAILROAD_TRACK :{WHITE}No suita STR_1007_ALREADY_BUILT :{WHITE}...already built STR_1008_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Must remove railway track first STR_100A_RAILROAD_CONSTRUCTION :{WHITE}Railway Construction +STR_TITLE_ELRAIL_CONSTRUCTION :{WHITE}Electrified Railway Construction STR_100B_MONORAIL_CONSTRUCTION :{WHITE}Monorail Construction STR_100C_MAGLEV_CONSTRUCTION :{WHITE}MagLev Construction STR_100D_SELECT_RAIL_BRIDGE :{WHITE}Select Rail Bridge @@ -1454,6 +1455,7 @@ STR_1012_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Can't re STR_1013_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Can't remove signals from here... STR_1014_TRAIN_DEPOT_ORIENTATION :{WHITE}Train Depot Orientation STR_1015_RAILROAD_CONSTRUCTION :Railway construction +STR_TOOLB_ELRAIL_CONSTRUCTION :Electrified Railway construction STR_1016_MONORAIL_CONSTRUCTION :Monorail construction STR_1017_MAGLEV_CONSTRUCTION :MagLev construction STR_1018_BUILD_RAILROAD_TRACK :{BLACK}Build railway track @@ -2410,6 +2412,7 @@ STR_8819_TRAIN_TOO_LONG :{WHITE}Train to STR_881A_TRAINS_CAN_ONLY_BE_ALTERED :{WHITE}Trains can only be altered when stopped inside a depot STR_881B_TRAINS :{WHITE}{COMPANY} - {COMMA} Train{P "" s} STR_881C_NEW_RAIL_VEHICLES :{WHITE}New Rail Vehicles +STR_NEW_ELRAIL_VEHICLES :{WHITE}New Electric Rail Vehicles STR_881D_NEW_MONORAIL_VEHICLES :{WHITE}New Monorail Vehicles STR_881E_NEW_MAGLEV_VEHICLES :{WHITE}New Maglev Vehicles STR_881F_BUILD_VEHICLE :{BLACK}Build Vehicle @@ -2810,6 +2813,7 @@ STR_SIGN_LIST_CAPTION :{WHITE}Sign Lis ############ Lists rail types STR_RAIL_VEHICLES :Rail Vehicles +STR_ELRAIL_VEHICLES :Electrified Rail Vehicles STR_MONORAIL_VEHICLES :Monorail Vehicles STR_MAGLEV_VEHICLES :Maglev Vehicles diff --git a/misc.c b/misc.c index 948ef5ebf0..82df58142b 100644 --- a/misc.c +++ b/misc.c @@ -401,8 +401,6 @@ typedef struct LandscapePredefVar { byte transit_days_table_1[NUM_CARGO]; byte transit_days_table_2[NUM_CARGO]; - byte railwagon_by_cargo[3][NUM_CARGO]; - byte road_veh_by_cargo_start[NUM_CARGO]; byte road_veh_by_cargo_count[NUM_CARGO]; } LandscapePredefVar; @@ -419,7 +417,6 @@ void InitializeLandscapeVariables(bool only_constants) lpd = &_landscape_predef_var[_opt.landscape]; - memcpy(_cargoc.ai_railwagon, lpd->railwagon_by_cargo, sizeof(lpd->railwagon_by_cargo)); memcpy(_cargoc.ai_roadveh_start, lpd->road_veh_by_cargo_start,sizeof(lpd->road_veh_by_cargo_start)); memcpy(_cargoc.ai_roadveh_count, lpd->road_veh_by_cargo_count,sizeof(lpd->road_veh_by_cargo_count)); diff --git a/newgrf.c b/newgrf.c index 4507579c3d..7506852437 100644 --- a/newgrf.c +++ b/newgrf.c @@ -355,6 +355,9 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf engclass = 0; } else if (traction <= 0x27) { engclass = 1; + } else if (traction <= 0x31) { + engclass = 2; + ei[i].railtype = RAILTYPE_ELECTRIC; } else if (traction <= 0x41) { engclass = 2; } else { @@ -2309,12 +2312,8 @@ static void InitializeGRFSpecial(void) | (1 << 0x18) /* newrvs */ | (1 << 0x19) /* newships */ | (1 << 0x1A) /* newplanes */ - | (_patches.signal_side ? (1 << 0x1B) : 0); /* signalsontrafficside */ - /* Uncomment following if you want to fool the GRF file. - * Some GRF files will refuse to load without this - * but you can still squeeze something from them even - * without the support - i.e. USSet. --pasky */ - //| (1 << 0x1C); /* electrifiedrailway */ + | (_patches.signal_side ? (1 << 0x1B) : 0) /* signalsontrafficside */ + | (1 << 0x1C); /* electrifiedrailway */ _ttdpatch_flags[2] = (_patches.build_on_slopes ? (1 << 0x0D) : 0) /* buildonslopes */ | (_patches.build_on_slopes ? (1 << 0x15) : 0) /* buildoncoasts */ diff --git a/npf.c b/npf.c index 4dc59f41a7..2c7bd06caf 100644 --- a/npf.c +++ b/npf.c @@ -587,7 +587,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current) /* check correct rail type (mono, maglev, etc) */ if (type == TRANSPORT_RAIL) { RailType dst_type = GetTileRailType(dst_tile, src_trackdir); - if (!IsCompatibleRail(aystar->user_data[NPF_RAILTYPE], dst_type)) + if (!HASBIT(aystar->user_data[NPF_RAILTYPES], dst_type)) return; } @@ -661,7 +661,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current) * multiple targets that are spread around, we should perform a breadth first * search by specifiying CalcZero as our heuristic. */ -static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailType railtype, uint reverse_penalty) +static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty) { int r; NPFFoundTargetData result; @@ -703,7 +703,7 @@ static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start /* Initialize user_data */ _npf_aystar.user_data[NPF_TYPE] = type; _npf_aystar.user_data[NPF_OWNER] = owner; - _npf_aystar.user_data[NPF_RAILTYPE] = railtype; + _npf_aystar.user_data[NPF_RAILTYPES] = railtypes; /* GO! */ r = AyStarMain_Main(&_npf_aystar); @@ -721,7 +721,7 @@ static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start return result; } -NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype) +NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes) { AyStarNode start1; AyStarNode start2; @@ -735,15 +735,15 @@ NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir track start2.direction = trackdir2; start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR; - return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtype, 0); + return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtypes, 0); } -NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype) +NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes) { - return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtype); + return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtypes); } -NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty) +NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty) { AyStarNode start1; AyStarNode start2; @@ -759,15 +759,15 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir t /* perform a breadth first search. Target is NULL, * since we are just looking for any depot...*/ - return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtype, reverse_penalty); + return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtypes, reverse_penalty); } -NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype) +NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes) { - return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtype, 0); + return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtypes, 0); } -NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype) +NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes) { /* Okay, what we're gonna do. First, we look at all depots, calculate * the manhatten distance to get to each depot. We then sort them by diff --git a/npf.h b/npf.h index 26b268521e..c550edaebf 100644 --- a/npf.h +++ b/npf.h @@ -38,7 +38,7 @@ typedef struct NPFFindStationOrTileData { /* Meant to be stored in AyStar.target enum { /* Indices into AyStar.userdata[] */ NPF_TYPE = 0, /* Contains a TransportTypes value */ NPF_OWNER, /* Contains an Owner value */ - NPF_RAILTYPE, /* Contains the RailType value of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */ + NPF_RAILTYPES, /* Contains a bitmask the compatible RailTypes of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */ }; enum { /* Indices into AyStarNode.userdata[] */ @@ -64,28 +64,28 @@ typedef struct NPFFoundTargetData { /* Meant to be stored in AyStar.userpath */ /* Will search from the given tile and direction, for a route to the given * station for the given transport type. See the declaration of * NPFFoundTargetData above for the meaning of the result. */ -NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype); +NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes); /* Will search as above, but with two start nodes, the second being the * reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */ -NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype); +NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes); /* Will search a route to the closest depot. */ /* Search using breadth first. Good for little track choice and inaccurate * heuristic, such as railway/road.*/ -NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype); +NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes); /* Same as above but with two start nodes, the second being the reverse. Call * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path * orginated. All pathfs from the second node will have the given * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full * tile). */ -NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty); +NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty); /* Search by trying each depot in order of Manhattan Distance. Good for lots * of choices and accurate heuristics, such as water. */ -NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype); +NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes); void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v); diff --git a/openttd.c b/openttd.c index 15b20e1405..04143a0a9a 100644 --- a/openttd.c +++ b/openttd.c @@ -1238,6 +1238,75 @@ bool AfterLoadGame(void) } } + /* Elrails got added in rev 24 */ + if (CheckSavegameVersion(24)) { + Vehicle* v; + uint i; + TileIndex t; + bool make_elrail = false; + + for (i = 0; i < lengthof(_engines); i++) { + Engine* e = GetEngine(i); + if (e->type == VEH_Train && + (e->railtype != RAILTYPE_RAIL || RailVehInfo(i)->engclass == 2)) { + e->railtype++; + } + } + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train) { + RailType rt = GetEngine(v->engine_type)->railtype; + + v->u.rail.railtype = rt; + if (rt == RAILTYPE_ELECTRIC) make_elrail = true; + } + } + + /* .. so we convert the entire map from normal to elrail (so maintain "fairness") */ + for (t = 0; t < MapSize(); t++) { + switch (GetTileType(t)) { + case MP_RAILWAY: + if (GetRailType(t) > RAILTYPE_RAIL || make_elrail) AB(_m[t].m3, 0, 4, 1); + break; + + case MP_STREET: + if (IsLevelCrossing(t) && (GetRailTypeCrossing(t) > RAILTYPE_RAIL || make_elrail)) AB(_m[t].m4, 0, 4, 1); + break; + + case MP_STATION: + if (_m[t].m5 < 8 && (GB(_m[t].m3, 0, 4) > RAILTYPE_RAIL || make_elrail)) AB(_m[t].m3, 0, 4, 1); + break; + + case MP_TUNNELBRIDGE: + if (GB(_m[t].m5, 4, 4) == 0) { // tunnel? + if (GB(_m[t].m5, 2, 2) == 0) { // railway tunnel? + if (GB(_m[t].m3, 0, 4) > RAILTYPE_RAIL || make_elrail) AB(_m[t].m3, 0, 4, 1); + } + } else { + if (GB(_m[t].m5, 1, 2) == 0) { // railway bridge? + if (GB(_m[t].m5, 6, 1) == 0) { // bridge ending? + if (GB(_m[t].m3, 0, 4) > RAILTYPE_RAIL || make_elrail) AB(_m[t].m3, 0, 4, 1); + } else { + if (GB(_m[t].m3, 4, 4) > RAILTYPE_RAIL || make_elrail) AB(_m[t].m3, 4, 4, 1); + } + } + if ((_m[t].m5 & 0xF8) == 0xE0) { // bridge middle part with rails below? + if (GB(_m[t].m3, 0, 4) > RAILTYPE_RAIL || make_elrail) AB(_m[t].m3, 0, 4, 1); + } + } + break; + + default: + break; + } + } + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v); + } + + } + /* In version 16.1 of the savegame a player can decide if trains, which get * replaced, shall keep their old length. In all prior versions, just default * to false */ diff --git a/openttd.dsp b/openttd.dsp index b8e28ed7f3..f4e2cea228 100644 --- a/openttd.dsp +++ b/openttd.dsp @@ -209,6 +209,10 @@ SOURCE=.\economy.c # End Source File # Begin Source File +SOURCE=.\elrail.c +# End Source File +# Begin Source File + SOURCE=.\engine.c # End Source File # Begin Source File diff --git a/openttd.vcproj b/openttd.vcproj index 1fa63899de..3afcd36d9e 100644 --- a/openttd.vcproj +++ b/openttd.vcproj @@ -214,6 +214,9 @@ + + diff --git a/pathfind.c b/pathfind.c index b70e51887f..b6c268938e 100644 --- a/pathfind.c +++ b/pathfind.c @@ -454,7 +454,8 @@ typedef struct { void *userdata; TileIndex dest; - byte tracktype; + TransportType tracktype; + RailTypeMask railtypes; uint maxlength; HashLink *new_link; @@ -791,6 +792,11 @@ start_at: * bits, not just reachable ones, to prevent infinite loops. */ if (bits == 0 || TracksOverlap(allbits)) break; + if (!HASBIT(tpf->railtypes, GetRailType(tile))) { + bits = 0; + break; + } + /* If we reach here, the tile has exactly one track, and this track is reachable => Rail segment continues */ @@ -926,14 +932,15 @@ start_at: // new pathfinder for trains. better and faster. -void NewTrainPathfind(TileIndex tile, TileIndex dest, DiagDirection direction, NTPEnumProc* enum_proc, void* data) +void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypeMask railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data) { NewTrackPathFinder tpf; tpf.dest = dest; tpf.userdata = data; tpf.enum_proc = enum_proc; - tpf.tracktype = 0; + tpf.tracktype = TRANSPORT_RAIL; + tpf.railtypes = railtypes; tpf.maxlength = min(_patches.pf_maxlength * 3, 10000); tpf.nstack = 0; tpf.new_link = tpf.links; diff --git a/pathfind.h b/pathfind.h index 748ec5ab99..8796774dd2 100644 --- a/pathfind.h +++ b/pathfind.h @@ -68,6 +68,6 @@ typedef struct { } FindLengthOfTunnelResult; FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, DiagDirection direction); -void NewTrainPathfind(TileIndex tile, TileIndex dest, DiagDirection direction, NTPEnumProc* enum_proc, void* data); +void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypeMask railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data); #endif /* PATHFIND_H */ diff --git a/player.h b/player.h index 3195e1c7ff..ebc42646dd 100644 --- a/player.h +++ b/player.h @@ -248,6 +248,7 @@ static inline RailType GetBestRailtype(const Player* p) { if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV; if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO; + if (HasRailtypeAvail(p, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC; return RAILTYPE_RAIL; } diff --git a/rail.h b/rail.h index 83ed575b7f..e7c5f34137 100644 --- a/rail.h +++ b/rail.h @@ -9,7 +9,6 @@ #include "rail_map.h" #include "tile.h" - /** These are a combination of tracks and directions. Values are 0-5 in one direction (corresponding to the Track enum) and 8-13 in the other direction. */ typedef enum Trackdirs { @@ -110,8 +109,11 @@ typedef struct RailtypeInfo { /** sprite number difference between a piece of track on a snowy ground and the corresponding one on normal ground */ SpriteID snow_offset; - /** bitmask to the OTHER railtypes that can be used by an engine of THIS railtype */ - byte compatible_railtypes; + /** bitmask to the OTHER railtypes on which an engine of THIS railtype generates power */ + RailTypeMask powered_railtypes; + + /** bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel */ + RailTypeMask compatible_railtypes; /** * Offset between the current railtype and normal rail. This means that:

      @@ -478,6 +480,11 @@ static inline bool IsCompatibleRail(RailType enginetype, RailType tiletype) return HASBIT(GetRailTypeInfo(enginetype)->compatible_railtypes, tiletype); } +static inline bool HasPowerOnRail(RailType enginetype, RailType tiletype) +{ + return HASBIT(GetRailTypeInfo(enginetype)->powered_railtypes, tiletype); +} + /** * Checks if the given tracks overlap, ie form a crossing. Basically this * means when there is more than one track on the tile, exept when there are @@ -497,4 +504,13 @@ static inline bool TracksOverlap(TrackBits bits) void DrawTrainDepotSprite(int x, int y, int image, RailType railtype); void DrawDefaultWaypointSprite(int x, int y, RailType railtype); + +/** + * Draws overhead wires and pylons for electric railways. + * @param ti The TileInfo struct of the tile being drawn + * @see DrawCatenaryRailway + */ +void DrawCatenary(const TileInfo *ti); + +uint GetRailFoundation(uint tileh, uint bits); #endif /* RAIL_H */ diff --git a/rail_cmd.c b/rail_cmd.c index 039acf9bd5..75e0263f17 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -896,11 +896,13 @@ int32 CmdRemoveSignalTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CmdSignalTrackHelper(x, y, flags, p1, SETBIT(p2, 0)); } -typedef int32 DoConvertRailProc(TileIndex tile, uint totype, bool exec); +typedef int32 DoConvertRailProc(TileIndex tile, RailType totype, bool exec); -static int32 DoConvertRail(TileIndex tile, uint totype, bool exec) +static int32 DoConvertRail(TileIndex tile, RailType totype, bool exec) { - if (!CheckTileOwnership(tile) || !EnsureNoVehicle(tile)) return CMD_ERROR; + if (!CheckTileOwnership(tile)) return CMD_ERROR; + + if (!EnsureNoVehicle(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR; // tile is already of requested type? if (GetRailType(tile) == totype) return CMD_ERROR; @@ -1297,6 +1299,9 @@ static void DrawTrackBits(TileInfo* ti, TrackBits track, bool earth, bool snow, if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w); if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e); } + + if (GB(_m[ti->tile].m3, 0, 4) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + } static void DrawTile_Track(TileInfo *ti) @@ -1388,6 +1393,8 @@ static void DrawTile_Track(TileInfo *ti) DrawGroundSprite(image); + if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + foreach_draw_tile_seq(seq, cust->seq) { DrawSpecialBuilding( seq->image + relocation, 0, ti, @@ -1420,6 +1427,8 @@ static void DrawTile_Track(TileInfo *ti) DrawGroundSprite(image); + if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + for (; drss->image != 0; drss++) { DrawSpecialBuilding( drss->image, type < 4 ? rti->total_offset : 0, ti, diff --git a/rail_map.h b/rail_map.h index 5a3828282f..a74982cf11 100644 --- a/rail_map.h +++ b/rail_map.h @@ -32,13 +32,16 @@ typedef enum RailTileSubtypes { typedef enum RailTypes { - RAILTYPE_RAIL = 0, - RAILTYPE_MONO = 1, - RAILTYPE_MAGLEV = 2, + RAILTYPE_RAIL = 0, + RAILTYPE_ELECTRIC = 1, + RAILTYPE_MONO = 2, + RAILTYPE_MAGLEV = 3, RAILTYPE_END, INVALID_RAILTYPE = 0xFF } RailType; +typedef byte RailTypeMask; + static inline RailType GetRailType(TileIndex t) { return (RailType)GB(_m[t].m3, 0, 4); diff --git a/railtypes.h b/railtypes.h index 12180c352a..1b9b665c49 100644 --- a/railtypes.h +++ b/railtypes.h @@ -40,8 +40,11 @@ const RailtypeInfo _railtypes[] = { /* Offset of snow tiles */ SPR_RAIL_SNOW_OFFSET, + /* Powered railtypes */ + 1 << RAILTYPE_RAIL | 1 << RAILTYPE_ELECTRIC, + /* Compatible railtypes */ - (1 << RAILTYPE_RAIL), + 1 << RAILTYPE_RAIL | 1 << RAILTYPE_ELECTRIC, /* main offset */ 0, @@ -50,6 +53,56 @@ const RailtypeInfo _railtypes[] = { 0, }, + /** Electrified railway */ + { /* Main Sprites */ + { SPR_RAIL_TRACK_Y, SPR_RAIL_TRACK_N_S, SPR_RAIL_TRACK_BASE, SPR_RAIL_SINGLE_Y, SPR_RAIL_SINGLE_X, + SPR_RAIL_SINGLE_NORTH, SPR_RAIL_SINGLE_SOUTH, SPR_RAIL_SINGLE_EAST, SPR_RAIL_SINGLE_WEST, + SPR_CROSSING_OFF_X_RAIL, + SPR_TUNNEL_ENTRY_REAR_RAIL + }, + + /* GUI sprites */ + { + SPR_BUILD_NS_ELRAIL, + SPR_BUILD_X_ELRAIL, + SPR_BUILD_EW_ELRAIL, + SPR_BUILD_Y_ELRAIL, + SPR_OPENTTD_BASE + 0, + 0x50E, + SPR_BUILD_TUNNEL_ELRAIL, + SPR_IMG_CONVERT_RAIL + }, + + { + SPR_CURSOR_NS_ELRAIL, + SPR_CURSOR_SWNE_ELRAIL, + SPR_CURSOR_EW_ELRAIL, + SPR_CURSOR_NWSE_ELRAIL, + SPR_CURSOR_AUTORAIL, + SPR_CURSOR_RAIL_DEPOT, + SPR_CURSOR_TUNNEL_ELRAIL, + SPR_CURSOR_CONVERT_RAIL + }, + + /* strings */ + { STR_TITLE_ELRAIL_CONSTRUCTION }, + + /* Offset of snow tiles */ + SPR_RAIL_SNOW_OFFSET, + + /* Powered railtypes */ + 1 << RAILTYPE_ELECTRIC, + + /* Compatible railtypes */ + 1 << RAILTYPE_ELECTRIC | 1 << RAILTYPE_RAIL, + + /* main offset */ + 0, + + /* bridge offset */ + 0 + }, + /** Monorail */ { /* Main Sprites */ { SPR_MONO_TRACK_Y, SPR_MONO_TRACK_N_S, SPR_MONO_TRACK_BASE, SPR_MONO_SINGLE_Y, SPR_MONO_SINGLE_X, @@ -83,8 +136,11 @@ const RailtypeInfo _railtypes[] = { /* Offset of snow tiles */ SPR_MONO_SNOW_OFFSET, + /* Powered railtypes */ + 1 << RAILTYPE_MONO, + /* Compatible Railtypes */ - (1 << RAILTYPE_MONO), + 1 << RAILTYPE_MONO, /* main offset */ 82, @@ -126,8 +182,11 @@ const RailtypeInfo _railtypes[] = { /* Offset of snow tiles */ SPR_MGLV_SNOW_OFFSET, + /* Powered railtypes */ + 1 << RAILTYPE_MAGLEV, + /* Compatible Railtypes */ - (1 << RAILTYPE_MAGLEV), + 1 << RAILTYPE_MAGLEV, /* main offset */ 164, diff --git a/road_cmd.c b/road_cmd.c index 854c59cff9..20505c9591 100644 --- a/road_cmd.c +++ b/road_cmd.c @@ -787,6 +787,7 @@ static void DrawTile_Road(TileInfo *ti) } DrawGroundSprite(image); + if (GB(_m[ti->tile].m4, 0, 4) == RAILTYPE_ELECTRIC) DrawCatenary(ti); break; } diff --git a/saveload.c b/saveload.c index 3b304f445e..75f75c6d06 100644 --- a/saveload.c +++ b/saveload.c @@ -30,7 +30,7 @@ #include "variables.h" #include -const uint16 SAVEGAME_VERSION = 23; +const uint16 SAVEGAME_VERSION = 24; uint16 _sl_version; /// the major savegame version identifier byte _sl_minor_version; /// the minor savegame version, DO NOT USE! diff --git a/station_cmd.c b/station_cmd.c index 986e732411..1cbad1c0d1 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -1959,6 +1959,8 @@ static void DrawTile_Station(TileInfo *ti) // but this is something else. If AI builds station with 114 it looks all weird DrawGroundSprite(image); + if (GB(_m[ti->tile].m3, 0, 4) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + foreach_draw_tile_seq(dtss, t->seq) { image = dtss->image + relocation; image += offset; diff --git a/table/elrail_data.h b/table/elrail_data.h new file mode 100644 index 0000000000..32a2834838 --- /dev/null +++ b/table/elrail_data.h @@ -0,0 +1,362 @@ +/* $Id */ +/** @file elrail_data.h Stores all the data for overhead wire and pylon drawing. @see elrail.c */ + +#ifndef ELRAIL_DATA_H +#define ELRAIL_DATA_H + +/** Tile Location group. This defines whether the X and or Y coordinate of a tile is even */ +typedef enum TLG { + XEVEN_YEVEN = 0, + XEVEN_YODD = 1, + XODD_YEVEN = 2, + XODD_YODD = 3, + TLG_END +} TLG; + +/** When determining the pylon configuration on the edge, two tiles are taken into account: + * the tile being drawn itself (the home tile, the one in ti->tile), and the neighbouring tile + */ +typedef enum { + TS_HOME = 0, + TS_NEIGHBOUR = 1, + + TS_END +} TileSource; + +enum { + TRACKS_AT_PCP = 6 +}; + +/** Which PPPs are possible at all on a given PCP */ +static byte AllowedPPPonPCP[DIAGDIR_END] = { + 1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW, + 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, + 1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW, + 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, +}; + +/** Which of the PPPs are inside the tile. For the two PPPs on the tile border the following system is used: + if you rotate the PCP so that it is in the north, the eastern PPP belongs to the tile. */ +static byte OwnedPPPonPCP[DIAGDIR_END] = { + 1 << DIR_SE | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W, + 1 << DIR_N | 1 << DIR_SW | 1 << DIR_W | 1 << DIR_NW, + 1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_NW, + 1 << DIR_NE | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S +}; + +/** Preferred points of each trackbit. Those are the ones perpendicular to the track, plus the point in + extension of the track (to mark end-of-track).*/ +static byte PreferredPPPofTrackBitAtPCP[TRACK_END][DIAGDIR_END] = { + {1 << DIR_NE | 1 << DIR_SE | 1 << DIR_NW, 0xFF, 1 << DIR_SE | 1 << DIR_SW | 1 << DIR_NW, 0xFF }, /* X */ + {0xFF, 1 << DIR_NE | 1 << DIR_SE | 1 << DIR_SW, 0xFF, 1 << DIR_SW | 1 << DIR_NW | 1 << DIR_NE }, /* Y */ + {1 << DIR_E | 1 << DIR_N | 1 << DIR_S, 0xFF, 0xFF, 1 << DIR_W | 1 << DIR_N | 1 << DIR_S}, /* UPPER */ + {0xFF, 1 << DIR_E | 1 << DIR_N | 1 << DIR_S, 1 << DIR_W | 1 << DIR_N | 1 << DIR_S, 0xFF}, /* LOWER */ + {0xFF, 0xFF, 1 << DIR_S | 1 << DIR_E | 1 << DIR_W, 1 << DIR_N | 1 << DIR_E | 1 << DIR_W}, /* LEFT */ + {1 << DIR_N | 1 << DIR_E | 1 << DIR_W, 1 << DIR_S | 1 << DIR_E | 1 << DIR_W, 0xFF, 0xFF}, /* RIGHT */ +}; + +#define NUM_IGNORE_GROUPS 3 +/** In case we have a staight line, we place pylon only every two tiles, so there are certain tiles + which we ignore. A straight line is found if we have exactly two preferred points.*/ +static byte IgnoredPCP[NUM_IGNORE_GROUPS][TLG_END][DIAGDIR_END] = { + { + {1 << DIR_N | 1 << DIR_S , 1 << DIR_NE | 1 << DIR_SW, 1 << DIR_NW | 1 << DIR_SE, 1 << DIR_W | 1 << DIR_E}, + {0xFF , 1 << DIR_E | 1 << DIR_W, 1 << DIR_NW | 1 << DIR_SE, 1 << DIR_NE | 1 << DIR_SW}, + {1 << DIR_NW | 1 << DIR_SE, 1 << DIR_NE | 1 << DIR_SW, 1 << DIR_N | 1 << DIR_S , 0xFF}, + {1 << DIR_NW | 1 << DIR_SE, 0xFF , 0xFF, 1 << DIR_NE | 1 << DIR_SW} + }, + { + {1 << DIR_E | 1 << DIR_W, 1 << DIR_N | 1 << DIR_S, 0xFF, 1 << DIR_E | 1 << DIR_W}, + {0xFF, 0xFF, 1 << DIR_N | 1 << DIR_S, 1 << DIR_N | 1 << DIR_S}, + {0xFF, 1 << DIR_E | 1 << DIR_W, 1 << DIR_E | 1 << DIR_W, 1 << DIR_N | 1 << DIR_S}, + {1 << DIR_N | 1 << DIR_S, 1 << DIR_N | 1 << DIR_S, 0xFF, 1 << DIR_E | 1 << DIR_W} + }, + { + {0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 1 << DIR_E | 1 << DIR_W, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF}, + {1 << DIR_E | 1 << DIR_W, 0xFF, 0xFF, 0xFF} + } +}; + +/** Which pylons can definately NOT be built */ +static byte DisallowedPPPofTrackBitAtPCP[TRACK_END][DIAGDIR_END] = { + {1 << DIR_SW | 1 << DIR_NE, 0, 1 << DIR_SW | 1 << DIR_NE, 0 }, /* X */ + {0, 1 << DIR_NW | 1 << DIR_SE, 0, 1 << DIR_NW | 1 << DIR_SE}, /* Y */ + {1 << DIR_W | 1 << DIR_E, 0, 0, 1 << DIR_W | 1 << DIR_E }, /* UPPER */ + {0, 1 << DIR_W | 1 << DIR_E, 1 << DIR_W | 1 << DIR_E, 0 }, /* LOWER */ + {0, 0, 1 << DIR_S | 1 << DIR_N, 1 << DIR_N | 1 << DIR_S }, /* LEFT */ + {1 << DIR_S | 1 << DIR_N, 1 << DIR_S | 1 << DIR_N, 0, 0, }, /* RIGHT */ +}; + +typedef struct { + SpriteID image; + int8 x_offset; + int8 y_offset; + int8 x_size; + int8 y_size; + int8 z_size; + int8 z_offset; +} SortableSpriteStruct; + +enum { + /** Distance between wire and rail */ + ELRAIL_ELEVATION = 8, + /** Corrects an off-by-one error in some places (tileh 12 and 9) (TODO -- find source of error) */ + ELRAIL_ELEV_CORR = ELRAIL_ELEVATION + 1, + /** Wires that a draw one level higher than the north corner. */ + ELRAIL_ELEVRAISE = ELRAIL_ELEVATION + TILE_HEIGHT +}; + +static const SortableSpriteStruct CatenarySpriteData[] = { +/* X direction */ + /* Flat tiles: */ + /* Wires */ + { SPR_WIRE_X_SW, 0, 8, 16, 1, 1, ELRAIL_ELEVATION }, //! 0: Wire in X direction, pylon on the SW end only + { SPR_WIRE_X_NE, 0, 8, 16, 1, 1, ELRAIL_ELEVATION }, //! 1: Wire in X direction, pylon on the NE end + { SPR_WIRE_X_SHORT, 0, 8, 16, 1, 1, ELRAIL_ELEVATION }, //! 2: Wire in X direction, pylon on both ends + + /* "up" tiles */ + /* Wires */ + { SPR_WIRE_X_SW_UP, 0, 8, 16, 8, 1, ELRAIL_ELEVRAISE }, //! 3: Wire in X pitch up, pylon on the SW end only + { SPR_WIRE_X_NE_UP, 0, 8, 16, 8, 1, ELRAIL_ELEVRAISE }, //! 4: Wire in X pitch up, pylon on the NE end + { SPR_WIRE_X_SHORT_UP, 0, 8, 16, 8, 1, ELRAIL_ELEVRAISE }, //! 5: Wire in X pitch up, pylon on both ends + + /* "down" tiles */ + /* Wires */ + { SPR_WIRE_X_SW_DOWN, 0, 8, 16, 8, 1, ELRAIL_ELEV_CORR }, //! 6: Wire in X pitch down, pylon on the SW end + { SPR_WIRE_X_NE_DOWN, 0, 8, 16, 8, 1, ELRAIL_ELEV_CORR }, //! 7: Wire in X pitch down, pylon on the NE end + { SPR_WIRE_X_SHORT_DOWN, 0, 8, 16, 8, 1, ELRAIL_ELEV_CORR }, //! 8: Wire in X pitch down, pylon on both ends + + +/* Y direction */ + /* Flat tiles: */ + /* Wires */ + { SPR_WIRE_Y_SE, 8, 0, 1, 16, 1, ELRAIL_ELEVATION }, //! 9: Wire in Y direction, pylon on the SE end only + { SPR_WIRE_Y_NW, 8, 0, 1, 16, 1, ELRAIL_ELEVATION }, //!10: Wire in Y direction, pylon on the NW end + { SPR_WIRE_Y_SHORT, 8, 0, 1, 16, 1, ELRAIL_ELEVATION }, //!11: Wire in Y direction, pylon on both ends + + /* "up" tiles */ + /* Wires */ + { SPR_WIRE_Y_SE_UP, 8, 0, 8, 16, 1, ELRAIL_ELEVRAISE }, //!12: Wire in Y pitch up, pylon on the SE end only + { SPR_WIRE_Y_NW_UP, 8, 0, 8, 16, 1, ELRAIL_ELEVRAISE }, //!13: Wire in Y pitch up, pylon on the NW end + { SPR_WIRE_Y_SHORT_UP, 8, 0, 8, 16, 1, ELRAIL_ELEVRAISE }, //!14: Wire in Y pitch up, pylon on both ends + + /* "down" tiles */ + /* Wires */ + { SPR_WIRE_Y_SE_DOWN, 8, 0, 8, 16, 1, ELRAIL_ELEV_CORR }, //!15: Wire in Y pitch down, pylon on the SE end + { SPR_WIRE_Y_NW_DOWN, 8, 0, 8, 16, 1, ELRAIL_ELEV_CORR }, //!16: Wire in Y pitch down, pylon on the NW end + { SPR_WIRE_Y_SHORT_DOWN, 8, 0, 8, 16, 1, ELRAIL_ELEV_CORR }, //!17: Wire in Y pitch down, pylon on both ends + +/* NS Direction */ + { SPR_WIRE_NS_SHORT, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!18: LEFT trackbit wire, pylon on both ends + { SPR_WIRE_NS_SHORT, 0, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!19: RIGHT trackbit wire, pylon on both ends + + { SPR_WIRE_NS_N, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!20: LEFT trackbit wire, pylon on N end + { SPR_WIRE_NS_N, 0, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!21: RIGHT trackbit wire, pylon on N end + + { SPR_WIRE_NS_S, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!22: LEFT trackbit wire, pylon on S end + { SPR_WIRE_NS_S, 0, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!23: RIGHT trackbit wire, pylon on S end + +/* EW Direction */ + { SPR_WIRE_EW_SHORT, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!24: UPPER trackbit wire, pylon on both ends + { SPR_WIRE_EW_SHORT, 16, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!25: LOWER trackbit wire, pylon on both ends + + { SPR_WIRE_EW_W, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!28: UPPER trackbit wire, pylon on both ends + { SPR_WIRE_EW_W, 16, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!29: LOWER trackbit wire, pylon on both ends + + { SPR_WIRE_EW_E, 8, 0, 8, 8, 1, ELRAIL_ELEVATION }, //!32: UPPER trackbit wire, pylon on both ends + { SPR_WIRE_EW_E, 16, 8, 8, 8, 1, ELRAIL_ELEVATION }, //!33: LOWER trackbit wire, pylon on both ends + +/* Depots */ + { SPR_WIRE_DEPOT_SW, 0, 8, 8, 1, 1, ELRAIL_ELEVATION }, //!36: Wire for SW depot exit + { SPR_WIRE_DEPOT_NW, 8, 0, 1, 8, 1, ELRAIL_ELEVATION }, //!37: Wire for NW depot exit + { SPR_WIRE_DEPOT_NE, 0, 8, 8, 1, 1, ELRAIL_ELEVATION }, //!38: Wire for NE depot exit + { SPR_WIRE_DEPOT_SE, 8, 0, 1, 8, 1, ELRAIL_ELEVATION }, //!39: Wire for SE depot exit +}; + +/** Refers to a certain element of the catenary. + * Identifiers for Wires: + *

      1. Direction of the wire
      2. + *
      3. Slope of the tile for diagonals, placement inside the track for horiz/vertical pieces
      4. + *
      5. Place where a pylon shoule be
      + * Identifiers for Pylons: + *
      1. Direction of the wire
      2. + *
      3. Slope of the tile
      4. + *
      5. Position of the Pylon relative to the track
      6. + *
      7. Position of the Pylon inside the tile
      + */ +typedef enum { + WIRE_X_FLAT_SW, + WIRE_X_FLAT_NE, + WIRE_X_FLAT_BOTH, + + WIRE_X_UP_SW, + WIRE_X_UP_NE, + WIRE_X_UP_BOTH, + + WIRE_X_DOWN_SW, + WIRE_X_DOWN_NE, + WIRE_X_DOWN_BOTH, + + WIRE_Y_FLAT_SE, + WIRE_Y_FLAT_NW, + WIRE_Y_FLAT_BOTH, + + WIRE_Y_UP_SE, + WIRE_Y_UP_NW, + WIRE_Y_UP_BOTH, + + WIRE_Y_DOWN_SE, + WIRE_Y_DOWN_NW, + WIRE_Y_DOWN_BOTH, + + WIRE_NS_W_BOTH, + WIRE_NS_E_BOTH, + + WIRE_NS_W_N, + WIRE_NS_E_N, + + WIRE_NS_W_S, + WIRE_NS_E_S, + + WIRE_EW_N_BOTH, + WIRE_EW_S_BOTH, + + WIRE_EW_N_W, + WIRE_EW_S_W, + + WIRE_EW_N_E, + WIRE_EW_S_E, + + WIRE_DEPOT_SW, + WIRE_DEPOT_NW, + WIRE_DEPOT_NE, + WIRE_DEPOT_SE, + + INVALID_CATENARY = 0xFF +} CatenarySprite; + +/* This array stores which track bits can meet at a tile edge */ +static const Track PPPtracks[DIAGDIR_END][TRACKS_AT_PCP] = { + {TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, + {TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, + {TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, + {TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, +}; + +/* takes each of the 8 track bits from the array above and + assigns it to the home tile or neighbour tile */ +static const TileSource trackorigin[DIAGDIR_END][TRACKS_AT_PCP] = { + {TS_HOME, TS_NEIGHBOUR, TS_HOME , TS_NEIGHBOUR, TS_NEIGHBOUR, TS_HOME }, + {TS_HOME, TS_NEIGHBOUR, TS_NEIGHBOUR, TS_HOME , TS_NEIGHBOUR, TS_HOME }, + {TS_HOME, TS_NEIGHBOUR, TS_NEIGHBOUR, TS_HOME , TS_HOME , TS_NEIGHBOUR}, + {TS_HOME, TS_NEIGHBOUR, TS_HOME , TS_NEIGHBOUR, TS_HOME , TS_NEIGHBOUR}, +}; + +/* Several PPPs maybe exist, here they are sorted in order of preference. */ +static const Direction PPPorder[DIAGDIR_END][TLG_END][DIR_END] = { /* X - Y */ + { /* PCP 0 */ + {DIR_NE, DIR_NW, DIR_SE, DIR_SW, DIR_N, DIR_E, DIR_S, DIR_W}, /* evn - evn */ + {DIR_NE, DIR_SE, DIR_SW, DIR_NW, DIR_S, DIR_W, DIR_N, DIR_E}, /* evn - odd */ + {DIR_SW, DIR_NW, DIR_NE, DIR_SE, DIR_S, DIR_W, DIR_N, DIR_E}, /* odd - evn */ + {DIR_SW, DIR_SE, DIR_NE, DIR_NW, DIR_N, DIR_E, DIR_S, DIR_W}, /* odd - odd */ + }, {/* PCP 1 */ + {DIR_NE, DIR_NW, DIR_SE, DIR_SW, DIR_S, DIR_E, DIR_N, DIR_W}, /* evn - evn */ + {DIR_NE, DIR_SE, DIR_SW, DIR_NW, DIR_N, DIR_W, DIR_S, DIR_E}, /* evn - odd */ + {DIR_SW, DIR_NW, DIR_NE, DIR_SE, DIR_N, DIR_W, DIR_S, DIR_E}, /* odd - evn */ + {DIR_SW, DIR_SE, DIR_NE, DIR_NW, DIR_S, DIR_E, DIR_N, DIR_W}, /* odd - odd */ + }, {/* PCP 2 */ + {DIR_NE, DIR_NW, DIR_SE, DIR_SW, DIR_S, DIR_W, DIR_N, DIR_E}, /* evn - evn */ + {DIR_NE, DIR_SE, DIR_SW, DIR_NW, DIR_N, DIR_E, DIR_S, DIR_W}, /* evn - odd */ + {DIR_SW, DIR_NW, DIR_NE, DIR_SE, DIR_N, DIR_E, DIR_S, DIR_W}, /* odd - evn */ + {DIR_SW, DIR_SE, DIR_NE, DIR_NW, DIR_S, DIR_W, DIR_N, DIR_E}, /* odd - odd */ + }, {/* PCP 3 */ + {DIR_NE, DIR_NW, DIR_SE, DIR_SW, DIR_N, DIR_W, DIR_S, DIR_E}, /* evn - evn */ + {DIR_NE, DIR_SE, DIR_SW, DIR_NW, DIR_S, DIR_E, DIR_N, DIR_W}, /* evn - odd */ + {DIR_SW, DIR_NW, DIR_NE, DIR_SE, DIR_S, DIR_E, DIR_N, DIR_W}, /* odd - evn */ + {DIR_SW, DIR_SE, DIR_NE, DIR_NW, DIR_N, DIR_W, DIR_S, DIR_E}, /* odd - odd */ + } +}; +/* Geometric placement of the PCP relative to the tile origin */ +static const char x_pcp_offsets[DIAGDIR_END] = {0, 8, 15, 8}; +static const char y_pcp_offsets[DIAGDIR_END] = {8, 15, 8, 0}; +/* Geometric placement of the PPP relative to the PCP*/ +static const char x_ppp_offsets[DIR_END] = {-3, -4, -3, 0, +3, +4, +3, 0}; +static const char y_ppp_offsets[DIR_END] = {-3, 0, +3, +4, +3, 0, -3, -4}; +/* The type of pylon to draw at each PPP */ +static const SpriteID pylons_normal[] = { + SPR_PYLON_EW_N, + SPR_PYLON_Y_NE, + SPR_PYLON_NS_E, + SPR_PYLON_X_SE, + SPR_PYLON_EW_S, + SPR_PYLON_Y_SW, + SPR_PYLON_NS_W, + SPR_PYLON_X_NW +}; + +static const SpriteID pylons_bridge[] = { + SPR_PYLON_X_NW, + SPR_PYLON_X_SE, + SPR_PYLON_Y_NE, + SPR_PYLON_Y_SW +}; + +/* Maps a track bit onto two PCP positions */ +static const byte PCPpositions[TRACK_END][2] = { + {0, 2}, /* X */ + {1, 3}, /* Y */ + {3, 0}, /* UPPER */ + {1, 2}, /* LOWER */ + {2, 3}, /* LEFT */ + {0, 1}, /* RIGHT */ +}; + +/* Selects a Wire (with white and grey ends) depending on whether: + a) none (should never happen) + b) the first + c) the second + d) both + PCP exists.*/ +static const CatenarySprite Wires[5][TRACK_END][4] = { + { /* Tileh == 0 */ + {INVALID_CATENARY, WIRE_X_FLAT_NE, WIRE_X_FLAT_SW, WIRE_X_FLAT_BOTH}, + {INVALID_CATENARY, WIRE_Y_FLAT_SE, WIRE_Y_FLAT_NW, WIRE_Y_FLAT_BOTH}, + {INVALID_CATENARY, WIRE_EW_N_W, WIRE_EW_N_E, WIRE_EW_N_BOTH}, + {INVALID_CATENARY, WIRE_EW_S_E, WIRE_EW_S_W, WIRE_EW_S_BOTH}, + {INVALID_CATENARY, WIRE_NS_W_S, WIRE_NS_W_N, WIRE_NS_W_BOTH}, + {INVALID_CATENARY, WIRE_NS_E_N, WIRE_NS_E_S, WIRE_NS_E_BOTH}, + }, { /* Tileh == 3 */ + {INVALID_CATENARY, WIRE_X_UP_NE, WIRE_X_UP_SW, WIRE_X_UP_BOTH}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + }, { /* Tileh == 6 */ + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, WIRE_Y_UP_SE, WIRE_Y_UP_NW, WIRE_Y_UP_BOTH}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + }, { /* Tileh == 9 */ + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, WIRE_Y_DOWN_SE, WIRE_Y_DOWN_NW, WIRE_Y_DOWN_BOTH}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + }, { /* Tileh == 12 */ + {INVALID_CATENARY, WIRE_X_DOWN_NE, WIRE_X_DOWN_SW, WIRE_X_DOWN_BOTH}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + {INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY, INVALID_CATENARY}, + } +}; + +#endif /* ELRAIL_DATA_H */ + diff --git a/table/engines.h b/table/engines.h index b8fe401907..dc33ebafab 100644 --- a/table/engines.h +++ b/table/engines.h @@ -27,11 +27,13 @@ // Rail types // R = Conventional railway +// E = Electrified railway // M = Monorail // L = MagLev #define R 0 -#define M 1 -#define L 2 +#define E 1 +#define M 2 +#define L 3 // Climates // T = Temperate // A = Arctic @@ -65,10 +67,10 @@ const EngineInfo orig_engine_info[] = { MK( 20454, 20, 22, 30, R, A|S ), /* 20 Turner Turbo (Diesel) */ MK( 16071, 20, 22, 30, R, A|S ), /* 21 MJS 1000 (Diesel) */ MK( 20820, 20, 20, 25, R, T ), /* 22 SH '125' (Diesel) */ - MK( 16437, 20, 23, 30, R, T ), /* 23 SH '30' (Electric) */ - MK( 19359, 20, 23, 80, R, T ), /* 24 SH '40' (Electric) */ - MK( 23376, 20, 25, 30, R, T ), /* 25 'T.I.M.' (Electric) */ - MK( 26298, 20, 25, 50, R, T ), /* 26 'AsiaStar' (Electric) */ + MK( 16437, 20, 23, 30, E, T ), /* 23 SH '30' (Electric) */ + MK( 19359, 20, 23, 80, E, T ), /* 24 SH '40' (Electric) */ + MK( 23376, 20, 25, 30, E, T ), /* 25 'T.I.M.' (Electric) */ + MK( 26298, 20, 25, 50, E, T ), /* 26 'AsiaStar' (Electric) */ MW( 1827, 20, 20, 50, R, T|A|S|Y), /* 27 Passenger Carriage */ MW( 1827, 20, 20, 50, R, T|A|S|Y), /* 28 Mail Van */ MW( 1827, 20, 20, 50, R, T|A ), /* 29 Coal Truck */ @@ -306,6 +308,7 @@ const EngineInfo orig_engine_info[] = { #undef L #undef M #undef R +#undef E /** Writes the properties of a rail vehicle into the RailVehicleInfo struct. * @see RailVehicleInfo diff --git a/table/landscape_const.h b/table/landscape_const.h index d7c3179e77..8cf1083c0a 100644 --- a/table/landscape_const.h +++ b/table/landscape_const.h @@ -42,13 +42,6 @@ static const LandscapePredefVar _landscape_predef_var[4] = { 24, 255, 90, 255, 18, 28, 40, 255, 255, 255, 32, 30, }, - /* normal railveh by cargo */ - { - {27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38}, - {57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68}, - {89, 91, 90, 92, 93, 94, 95, 96, 97, 98, 99, 100} - }, - /* normal road veh by cargo start & count */ {116, 123, 126, 132, 135, 138, 141, 144, 147, 150, 153, 156}, {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} @@ -95,14 +88,6 @@ static const LandscapePredefVar _landscape_predef_var[4] = { 24, 255, 90, 255, 18, 28, 40, 255, 255, 60, 40, 30 }, - /* hilly railveh by cargo */ - { - {27, 29, 28, 30, 31, 32, 33, 34, 35, 39, 37, 38}, - {57, 59, 58, 60, 61, 62, 63, 64, 65, 69, 67, 68}, - {89, 91, 90, 92, 93, 94, 95, 96, 97, 101, 99, 100} - }, - - /* hilly road veh by cargo start & count */ {116, 123, 126, 132, 135, 138, 141, 144, 147, 159, 153, 156}, {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3}, @@ -150,13 +135,6 @@ static const LandscapePredefVar _landscape_predef_var[4] = { 24, 20, 90, 255, 15, 28, 40, 255, 255, 80, 255, 30 }, - /* desert railveh by cargo */ - { - {27, 43, 28, 30, 42, 32, 33, 34, 40, 41, 37, 38}, - {57, 73, 58, 60, 72, 62, 63, 64, 70, 71, 67, 68}, - {89, 105, 90, 92, 104, 94, 95, 96, 102, 103, 99, 100} - }, - /* desert road veh by cargo start & count */ {116, 171, 126, 132, 168, 138, 141, 144, 162, 165, 153, 156}, {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} @@ -203,13 +181,6 @@ static const LandscapePredefVar _landscape_predef_var[4] = { 24, 255, 90, 255, 30, 40, 60, 75, 25, 80, 255, 50 }, - /* candy railveh by cargo */ - { - {27, 44, 28, 50, 51, 49, 46, 48, 45, 47, 53, 52}, - {57, 74, 58, 80, 81, 79, 76, 78, 75, 77, 83, 82}, - {89, 106, 90, 112, 113, 111, 108, 110, 107, 109, 115, 114} - }, - /* candy road veh by cargo start & count */ {116, 174, 126, 186, 192, 189, 183, 177, 180, 201, 198, 195}, {7, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3} diff --git a/table/sprites.h b/table/sprites.h index 34fda3f647..f7e0817c29 100644 --- a/table/sprites.h +++ b/table/sprites.h @@ -51,7 +51,8 @@ enum Sprites { SPR_CANALS_BASE = 5382, SPR_SLOPES_BASE = SPR_CANALS_BASE + 70, SPR_AUTORAIL_BASE = SPR_SLOPES_BASE + 78, - SPR_2CCMAP_BASE = SPR_AUTORAIL_BASE + 55, + SPR_ELRAIL_BASE = SPR_AUTORAIL_BASE + 55, + SPR_2CCMAP_BASE = SPR_ELRAIL_BASE + 53, SPR_OPENTTD_BASE = SPR_2CCMAP_BASE + 256, SPR_BLOT = SPR_OPENTTD_BASE + 29, // colored circle (mainly used as vehicle profit marker and for sever compatibility) @@ -206,6 +207,54 @@ enum Sprites { OFFSET_TILEH_13 = 19, OFFSET_TILEH_14 = 16, + /* Elrail stuff */ + /* Wires. First identifier is the direction of the track, second is the required placement of the pylon. + "short" denotes a wire that requires a pylon on each end. Third identifier is the direction of the slope + (in positive coordinate direction) */ + SPR_WIRE_X_SHORT = SPR_ELRAIL_BASE + 3, + SPR_WIRE_Y_SHORT = SPR_ELRAIL_BASE + 4, + SPR_WIRE_EW_SHORT = SPR_ELRAIL_BASE + 5, + SPR_WIRE_NS_SHORT = SPR_ELRAIL_BASE + 6, + SPR_WIRE_X_SHORT_DOWN = SPR_ELRAIL_BASE + 7, + SPR_WIRE_Y_SHORT_UP = SPR_ELRAIL_BASE + 8, + SPR_WIRE_X_SHORT_UP = SPR_ELRAIL_BASE + 9, + SPR_WIRE_Y_SHORT_DOWN = SPR_ELRAIL_BASE + 10, + + SPR_WIRE_X_SW = SPR_ELRAIL_BASE + 11, + SPR_WIRE_Y_SE = SPR_ELRAIL_BASE + 12, + SPR_WIRE_EW_E = SPR_ELRAIL_BASE + 13, + SPR_WIRE_NS_S = SPR_ELRAIL_BASE + 14, + SPR_WIRE_X_SW_DOWN = SPR_ELRAIL_BASE + 15, + SPR_WIRE_Y_SE_UP = SPR_ELRAIL_BASE + 16, + SPR_WIRE_X_SW_UP = SPR_ELRAIL_BASE + 17, + SPR_WIRE_Y_SE_DOWN = SPR_ELRAIL_BASE + 18, + + SPR_WIRE_X_NE = SPR_ELRAIL_BASE + 19, + SPR_WIRE_Y_NW = SPR_ELRAIL_BASE + 20, + SPR_WIRE_EW_W = SPR_ELRAIL_BASE + 21, + SPR_WIRE_NS_N = SPR_ELRAIL_BASE + 22, + SPR_WIRE_X_NE_DOWN = SPR_ELRAIL_BASE + 23, + SPR_WIRE_Y_NW_UP = SPR_ELRAIL_BASE + 24, + SPR_WIRE_X_NE_UP = SPR_ELRAIL_BASE + 25, + SPR_WIRE_Y_NW_DOWN = SPR_ELRAIL_BASE + 26, + + /* Tunnel entries */ + SPR_WIRE_DEPOT_SW = SPR_ELRAIL_BASE + 27, + SPR_WIRE_DEPOT_NW = SPR_ELRAIL_BASE + 28, + SPR_WIRE_DEPOT_NE = SPR_ELRAIL_BASE + 29, + SPR_WIRE_DEPOT_SE = SPR_ELRAIL_BASE + 30, + + + /* Pylons, first identifier is the direction of the track, second the placement relative to the track */ + SPR_PYLON_Y_NE = SPR_ELRAIL_BASE + 31, + SPR_PYLON_Y_SW = SPR_ELRAIL_BASE + 32, + SPR_PYLON_X_NW = SPR_ELRAIL_BASE + 33, + SPR_PYLON_X_SE = SPR_ELRAIL_BASE + 34, + SPR_PYLON_EW_N = SPR_ELRAIL_BASE + 35, + SPR_PYLON_EW_S = SPR_ELRAIL_BASE + 36, + SPR_PYLON_NS_W = SPR_ELRAIL_BASE + 37, + SPR_PYLON_NS_E = SPR_ELRAIL_BASE + 38, + /* sprites for airports and airfields*/ /* Small airports are AIRFIELD, everything else is AIRPORT */ SPR_HELIPORT = 2633, @@ -955,6 +1004,13 @@ enum Sprites { SPR_BUBBLE_ABSORB_3 = 4761, SPR_BUBBLE_ABSORB_4 = 4762, + /* Electrified rail build menu */ + SPR_BUILD_NS_ELRAIL = SPR_ELRAIL_BASE + 39, + SPR_BUILD_X_ELRAIL = SPR_ELRAIL_BASE + 40, + SPR_BUILD_EW_ELRAIL = SPR_ELRAIL_BASE + 41, + SPR_BUILD_Y_ELRAIL = SPR_ELRAIL_BASE + 42, + SPR_BUILD_TUNNEL_ELRAIL = SPR_ELRAIL_BASE + 47, + /* road_gui.c */ SPR_IMG_ROAD_NW = 1309, SPR_IMG_ROAD_NE = 1310, @@ -1034,9 +1090,15 @@ typedef enum CursorSprites { SPR_CURSOR_EW_MAGLEV = 1273, SPR_CURSOR_NWSE_MAGLEV = 1274, + SPR_CURSOR_NS_ELRAIL = SPR_ELRAIL_BASE + 43, + SPR_CURSOR_SWNE_ELRAIL = SPR_ELRAIL_BASE + 44, + SPR_CURSOR_EW_ELRAIL = SPR_ELRAIL_BASE + 45, + SPR_CURSOR_NWSE_ELRAIL = SPR_ELRAIL_BASE + 46, + SPR_CURSOR_RAIL_STATION = 1300, SPR_CURSOR_TUNNEL_RAIL = 2434, + SPR_CURSOR_TUNNEL_ELRAIL = SPR_ELRAIL_BASE + 48, SPR_CURSOR_TUNNEL_MONO = 2435, SPR_CURSOR_TUNNEL_MAGLEV = 2436, diff --git a/train_cmd.c b/train_cmd.c index e5fd267724..4e433eef05 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -71,6 +71,46 @@ static void TrainCargoChanged(Vehicle* v) v->u.rail.cached_weight = weight; } +/** + * Recalculates the cached total power of a train. Should be called when the consist is changed + * @param v First vehicle of the consist. + */ +void TrainPowerChanged(Vehicle* v) +{ + const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type); + Vehicle* u; + uint32 power = 0; + + for (u = v; u != NULL; u = u->next) { + const RailVehicleInfo *rvi_u; + bool engine_has_power = true; + bool wagon_has_power = true; + + /* Power is not added for articulated parts */ + if (IsArticulatedPart(u)) continue; + + if (IsBridgeTile(u->tile) && IsBridgeMiddle(u->tile) && DiagDirToAxis(DirToDiagDir(u->direction)) == GetBridgeAxis(u->tile)) { + if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeOnBridge(u->tile))) engine_has_power = false; + if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeOnBridge(u->tile))) wagon_has_power = false; + } else { + if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false; + if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false; + } + + rvi_u = RailVehInfo(u->engine_type); + + if (engine_has_power) power += rvi_u->power; + if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON) && (wagon_has_power)) { + power += rvi_v->pow_wag_power; + } + } + + if (v->u.rail.cached_power != power) { + v->u.rail.cached_power = power; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + } +} + /** * Recalculates the cached stuff of a train. Should be called each time a vehicle is added * to/removed from the chain, and when the game is loaded. @@ -82,7 +122,6 @@ void TrainConsistChanged(Vehicle* v) const RailVehicleInfo *rvi_v; Vehicle *u; uint16 max_speed = 0xFFFF; - uint32 power = 0; EngineID first_engine; assert(v->type == VEH_Train); @@ -92,6 +131,7 @@ void TrainConsistChanged(Vehicle* v) rvi_v = RailVehInfo(v->engine_type); first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE; v->u.rail.cached_total_length = 0; + v->u.rail.compatible_railtypes = 0; for (u = v; u != NULL; u = u->next) { const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); @@ -102,6 +142,7 @@ void TrainConsistChanged(Vehicle* v) // update the 'first engine' u->u.rail.first_engine = (v == u) ? INVALID_ENGINE : first_engine; + u->u.rail.railtype = GetEngine(u->engine_type)->railtype; if (rvi_u->visual_effect != 0) { u->u.rail.cached_vis_effect = rvi_u->visual_effect; @@ -119,9 +160,6 @@ void TrainConsistChanged(Vehicle* v) } if (!IsArticulatedPart(u)) { - // power is the sum of the powers of all engines and powered wagons in the consist - power += rvi_u->power; - // check if its a powered wagon CLRBIT(u->u.rail.flags, VRF_POWEREDWAGON); if ((rvi_v->pow_wag_power != 0) && (rvi_u->flags & RVI_WAGON) && UsesWagonOverride(u)) { @@ -135,10 +173,15 @@ void TrainConsistChanged(Vehicle* v) if (u->u.rail.cached_vis_effect < 0x40) { /* wagon is powered */ SETBIT(u->u.rail.flags, VRF_POWEREDWAGON); // cache 'powered' status - power += rvi_v->pow_wag_power; } } + /* Do not count powered wagons for the compatible railtypes, as wagons always + have railtype normal */ + if (rvi_u->power > 0) { + v->u.rail.compatible_railtypes |= GetRailTypeInfo(u->u.rail.railtype)->powered_railtypes; + } + // max speed is the minimum of the speed limits of all vehicles in the consist if (!(rvi_u->flags & RVI_WAGON) || _patches.wagon_speed_limits) if (rvi_u->max_speed != 0 && !UsesWagonOverride(u)) @@ -159,7 +202,8 @@ void TrainConsistChanged(Vehicle* v) // store consist weight/max speed in cache v->u.rail.cached_max_speed = max_speed; - v->u.rail.cached_power = power; + + TrainPowerChanged(v); // recalculate cached weights too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) TrainCargoChanged(v); @@ -333,6 +377,7 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) if (speed > 0) { switch (v->u.rail.railtype) { case RAILTYPE_RAIL: + case RAILTYPE_ELECTRIC: case RAILTYPE_MONO: force = power / speed; //[N] force *= 22; @@ -1468,6 +1513,9 @@ static void ReverseTrainSwapVeh(Vehicle *v, int l, int r) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos); } + + /* Update train's power incase tiles were different rail type */ + TrainPowerChanged(v); } /* Check if the vehicle is a train and is on the tile we are testing */ @@ -1786,7 +1834,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); assert (trackdir != INVALID_TRACKDIR); - ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, NPF_INFINITE_PENALTY); + ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY); if (ftd.best_bird_dist == 0) { /* Found target */ tfdd.tile = ftd.node.tile; @@ -1805,7 +1853,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT); } - NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); + NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); if (tfdd.best_length == (uint)-1){ tfdd.reverse = true; // search in backwards direction @@ -1813,7 +1861,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT); } - NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); + NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd); } } @@ -1899,7 +1947,7 @@ static void HandleLocomotiveSmokeCloud(const Vehicle* v) // no smoke? if ((RailVehInfo(engtype)->flags & RVI_WAGON && effect_type == 0) || disable_effect || - GetEngine(engtype)->railtype > RAILTYPE_RAIL || + GetEngine(engtype)->railtype > RAILTYPE_ELECTRIC || v->vehstatus & VS_HIDDEN || v->u.rail.track & 0xC0) { continue; @@ -1961,6 +2009,7 @@ static void TrainPlayLeaveStationSound(const Vehicle* v) switch (GetEngine(engtype)->railtype) { case RAILTYPE_RAIL: + case RAILTYPE_ELECTRIC: SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v); break; @@ -2112,7 +2161,7 @@ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, trackdir = GetVehicleTrackdir(v); assert(trackdir != 0xff); - ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype); + ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes); if (ftd.best_trackdir == 0xff) { /* We are already at our target. Just do something */ @@ -2136,7 +2185,7 @@ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, fd.best_track = 0xFF; NewTrainPathfind(tile - TileOffsByDir(enterdir), v->dest_tile, - enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); + v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); if (fd.best_track == 0xff) { // blaha @@ -2190,7 +2239,7 @@ static bool CheckReverseTrain(Vehicle *v) assert(trackdir != 0xff); assert(trackdir_rev != 0xff); - ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype); + ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes); if (ftd.best_bird_dist != 0) { /* We didn't find anything, just keep on going straight ahead */ reverse_best = false; @@ -2206,7 +2255,7 @@ static bool CheckReverseTrain(Vehicle *v) fd.best_bird_dist = (uint)-1; fd.best_track_dist = (uint)-1; - NewTrainPathfind(v->tile, v->dest_tile, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd); + NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd); if (best_track != -1) { if (best_bird_dist != 0) { @@ -2575,7 +2624,7 @@ static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile) return IsTileOwner(tile, v->owner) && ( !IsFrontEngine(v) || - IsCompatibleRail(v->u.rail.railtype, GetRailType(tile)) + HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile)) ); } @@ -2585,9 +2634,10 @@ typedef struct { byte z_down; // fraction to remove when moving down } RailtypeSlowdownParams; -static const RailtypeSlowdownParams _railtype_slowdown[3] = { +static const RailtypeSlowdownParams _railtype_slowdown[] = { // normal accel {256/4, 256/2, 256/4, 2}, // normal + {256/4, 256/2, 256/4, 2}, // electrified {256/4, 256/2, 256/4, 2}, // monorail {0, 256/2, 256/4, 2}, // maglev }; @@ -2873,6 +2923,11 @@ static void TrainController(Vehicle *v) if (!(r&0x4)) { v->tile = gp.new_tile; + + if (GetTileRailType(gp.new_tile, chosen_track) != GetTileRailType(gp.old_tile, v->u.rail.track)) { + TrainPowerChanged(GetFirstVehicleInChain(v)); + } + v->u.rail.track = chosen_track; assert(v->u.rail.track); } diff --git a/train_gui.c b/train_gui.c index 51565980b1..160e8fe7d5 100644 --- a/train_gui.c +++ b/train_gui.c @@ -177,7 +177,7 @@ static void engine_drawing_loop(int *x, int *y, int *pos, int *sel, const Engine *e = GetEngine(i); const RailVehicleInfo *rvi = RailVehInfo(i); - if (!IsCompatibleRail(e->railtype, railtype) || !(rvi->flags & RVI_WAGON) != is_engine || + if (!HasPowerOnRail(e->railtype, railtype) || !(rvi->flags & RVI_WAGON) != is_engine || !HASBIT(e->player_avail, _local_player)) continue; @@ -208,7 +208,7 @@ static void NewRailVehicleWndProc(Window *w, WindowEvent *e) for (i = 0; i < NUM_TRAIN_ENGINES; i++) { const Engine *e = GetEngine(i); - if (IsCompatibleRail(e->railtype, railtype) + if (HasPowerOnRail(e->railtype, railtype) && HASBIT(e->player_avail, _local_player)) count++; } diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index b7d8466dd1..7445db1673 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -799,9 +799,9 @@ int32 DoConvertTunnelBridgeRail(TileIndex tile, uint totype, bool exec) // fast routine for getting the height of a middle bridge tile. 'tile' MUST be a middle bridge tile. -static uint GetBridgeHeight(const TileInfo *ti) +uint GetBridgeHeight(TileIndex t) { - TileIndex tile = GetSouthernBridgeEnd(ti->tile); + TileIndex tile = GetSouthernBridgeEnd(t); /* Return the height there (the height of the NORTH CORNER) * If the end of the bridge is on a tileh 7 (all raised, except north corner), @@ -930,6 +930,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) image += GetTunnelDirection(ti->tile) * 2; DrawGroundSprite(image); + if (GB(_m[ti->tile].m3, 0, 3) == RAILTYPE_ELECTRIC) DrawCatenary(ti); AddSortableSpriteToDraw(image+1, ti->x + 15, ti->y + 15, 1, 1, 8, (byte)ti->z); } else if (IsBridge(ti->tile)) { // XXX is this necessary? @@ -973,6 +974,8 @@ static void DrawTile_TunnelBridge(TileInfo *ti) DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]); } + if (GB(_m[ti->tile].m3, 0, 3) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + // draw ramp if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image); AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z); @@ -1029,7 +1032,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) // get bridge sprites b = GetBridgeSpriteTable(GetBridgeType(ti->tile), GetBridgePiece(ti->tile)) + base_offset; - z = GetBridgeHeight(ti) + 5; + z = GetBridgeHeight(ti->tile) + 5; // draw rail or road component image = b[0]; @@ -1054,6 +1057,8 @@ static void DrawTile_TunnelBridge(TileInfo *ti) if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z); } + if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC || GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); + if (ti->z + 5 == z) { // draw poles below for small bridges image = b[2]; @@ -1107,7 +1112,7 @@ static uint GetSlopeZ_TunnelBridge(const TileInfo* ti) if (_get_z_hint >= z + 8) return _get_z_hint; // actually on the bridge, but not yet in the shared area. - if (!IS_INT_INSIDE(x, 5, 10 + 1)) return GetBridgeHeight(ti) + 8; + if (!IS_INT_INSIDE(x, 5, 10 + 1)) return GetBridgeHeight(ti->tile) + 8; // in the shared area, assume that we're below the bridge, cause otherwise the hint would've caught it. // if rail or road below then it means it's possibly build on slope below the bridge. diff --git a/variables.h b/variables.h index c7c051ad34..b63a0cee7e 100644 --- a/variables.h +++ b/variables.h @@ -345,7 +345,6 @@ typedef struct { SpriteID sprites[NUM_CARGO]; byte transit_days_1[NUM_CARGO]; byte transit_days_2[NUM_CARGO]; - byte ai_railwagon[3][NUM_CARGO]; byte ai_roadveh_start[NUM_CARGO]; byte ai_roadveh_count[NUM_CARGO]; } CargoConst; diff --git a/vehicle.c b/vehicle.c index 6f85588237..0183d04c77 100644 --- a/vehicle.c +++ b/vehicle.c @@ -218,6 +218,10 @@ void AfterLoadVehicles(void) FOR_ALL_VEHICLES(v) { v->first = NULL; + if (v->type == VEH_Train) v->u.rail.first_engine = INVALID_ENGINE; + } + + FOR_ALL_VEHICLES(v) { if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v); } diff --git a/vehicle.h b/vehicle.h index d63e6b5f51..87d279449d 100644 --- a/vehicle.h +++ b/vehicle.h @@ -72,6 +72,7 @@ typedef struct VehicleRail { byte track; byte force_proceed; byte railtype; + RailTypeMask compatible_railtypes; byte flags; @@ -307,6 +308,7 @@ UnitID GetFreeUnitNumber(byte type); int LoadUnloadVehicle(Vehicle *v); void TrainConsistChanged(Vehicle *v); +void TrainPowerChanged(Vehicle *v); int32 GetTrainRunningCost(const Vehicle *v); int CheckTrainStoppedInDepot(const Vehicle *v); diff --git a/vehicle_gui.c b/vehicle_gui.c index 25b0f65772..31b8e9bf05 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -76,6 +76,7 @@ const StringID _vehicle_sort_listing[] = { static const StringID _rail_types_list[] = { STR_RAIL_VEHICLES, + STR_ELRAIL_VEHICLES, STR_MONORAIL_VEHICLES, STR_MAGLEV_VEHICLES, INVALID_STRING_ID @@ -450,7 +451,7 @@ static int CDECL VehicleValueSorter(const void *a, const void *b) * if used compined with show_cars set to false, it will work as intended. Replace window do it like that * this was a big hack even before show_outdated was added. Stupid newgrf :p */ static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, EngineID *selected_id, RailType railtype, - uint8 lines_drawn, bool is_engine, bool show_cars, bool show_outdated) + uint8 lines_drawn, bool is_engine, bool show_cars, bool show_outdated, bool show_compatible) { EngineID j; byte colour; @@ -472,7 +473,9 @@ static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, Engine colour = *sel == 0 ? 0xC : 0x10; if (!(ENGINE_AVAILABLE && show_outdated && RailVehInfo(i)->power && e->railtype == railtype)) { - if (e->railtype != railtype || !(rvi->flags & RVI_WAGON) != is_engine || + if ((!HasPowerOnRail(e->railtype, railtype) && show_compatible) + || (e->railtype != railtype && !show_compatible) + || !(rvi->flags & RVI_WAGON) != is_engine || !HASBIT(e->player_avail, _local_player)) continue; } /*else { @@ -522,16 +525,15 @@ static void SetupScrollStuffForReplaceWindow(Window *w) const Engine* e = GetEngine(eid); const EngineInfo* info = &_engine_info[eid]; + // left window contains compatible engines while right window only contains engines of the selected type if (ENGINE_AVAILABLE && ( (RailVehInfo(eid)->power != 0 && WP(w, replaceveh_d).wagon_btnstate) || - (RailVehInfo(eid)->power == 0 && !WP(w, replaceveh_d).wagon_btnstate) - ) && - e->railtype == railtype) { - if (_player_num_engines[eid] > 0 || EngineHasReplacementForPlayer(p, eid)) { + (RailVehInfo(eid)->power == 0 && !WP(w, replaceveh_d).wagon_btnstate))) { + if (HasPowerOnRail(e->railtype, railtype) && (_player_num_engines[eid] > 0 || EngineHasReplacementForPlayer(p, eid))) { if (sel[0] == count) selected_id[0] = eid; count++; } - if (HASBIT(e->player_avail, _local_player)) { + if (e->railtype == railtype && HASBIT(e->player_avail, _local_player)) { if (sel[1] == count2) selected_id[1] = eid; count2++; } @@ -647,12 +649,12 @@ static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int * engines to get more types.. Stays here until we have our own format * then it is exit!!! */ if (WP(w,replaceveh_d).wagon_btnstate) { - train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, true, false, true); // True engines - train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, true, false, false); // True engines - train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, false, false); // Feeble wagons + train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, true, false, true, true); // True engines + train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, true, false, false, false); // True engines + train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, false, false, false); // Feeble wagons } else { - train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, false, true, true); - train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, true, false); + train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, false, true, true, true); + train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, true, false, true); } break; }