GPL Code Repository - Page 4

GPL Code Repository

Discuss game development here, from a distinct game project to an accessible third-party mutator, down to the interaction and design of individual units if you like.

Moderator: Moderators

User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

I think the load command gives your script the desired unit number? In that case you could compare its height and if it's a towed gun attach it to the trailer piece while everything that isn't gets attached to some internal piece.
Archangel of Death
Posts: 854
Joined: 28 Jan 2005, 18:15

Post by Archangel of Death »

The angle finding script is quite a bit slower than the engines heading and pitch detection.
User avatar
rattle
Damned Developer
Posts: 8278
Joined: 01 Jun 2006, 13:15

Post by rattle »

Lowering the sleep time could work I guess... if anyone can think of a more accurate way feel free to tell.
Guessmyname wrote:Could this angle-finding script be used to fix the dodgy turret aiming anims you get with aircraft?
No idea... I haven't had any issues yet with turrets on aircraft. I have an aircraft which got two individual turrets turning on the x-axis and they seem to visually aim just fine.
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6240
Joined: 29 Apr 2005, 01:14

Post by FLOZi »

KDR_11k wrote:I think the load command gives your script the desired unit number? In that case you could compare its height and if it's a towed gun attach it to the trailer piece while everything that isn't gets attached to some internal piece.
Exactly.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7049
Joined: 16 Nov 2004, 13:08

Post by zwzsg »

Nice idea on the oil pump.

Mexxes scripts can use the argument the engine pass to SetSpeed to know how much metal there is in the ground. Any way you could use that to make your oil pump refill rate proportionnal to metal concentration?

For a script that allow a transport load X unit of type A, Y unit of type B, and and nothing else, see with Wotan. His TAWP mod use such a system. Hmm ok might not be very convenient to have to get a whole mod for just one script, and to get second hand scripts instead of the source.

So instead, get the ArmDuck from http://wormhole.tauniverse.com
It is a transport. It works both in TA and Spring. It has nice and complex script showcasing many stuff:

* Wheels that turns according to how the units is turning.heading.

* Auto-unload in formation. Ok Spring already has zone unload, but Spring's engine zone unload sometimes is a bit messy, units gets unloaded over each others, etc..., so even in Spring my auto unload can be useful.

* (plenty of other nifty stuff)

* And what interest you, a system to give a "weight" to each unit, and a max cargo weight for the transport. To use it, you must:
- change #define LIMITED_CARGO_HOLD FALSE into #define LIMITED_CARGO_HOLD TRUE into the ArmDuck script.
- Change the 3000 into whatever max sum of all loaded units "weight" you want in the line #define MAX_CARGO_HOLD 3000 of the ArmDuck Bos.
- Edit the file H2Weight, which contains the relationship between unit names and their "weight". Actually, it's the relation ship between unit height (that is the +- only unit property that can be measured ingame) and the unit "weight" that you choose. So this where you choose how much "weight" each unit.
- Edit the file "CavedogUnitsHeight.h" to report all the unit height. This must contains the real, actual height of the unit. The system use the command get UNIT_HEIGHT to identify units. Of course there must not be two units with the same height. Height are different under TA and under Spring. To measure a unit height, use the Caliper, from http://wormhole.tauniverse.com as well. So, yeah, you must spend an hour or two building every unit, moving it near the caliper, and reporting down the number into the CavedogUnitsHeight.h (btw, change that filename when it's not about OTA units any more).

Important note: the "weight" I'm talking about here has nothing to do with Spring mass tags.

There is two ways, that have nothing to do with each others:
- Spring's FBI tags, TransportMass in the FBI transport, and Mass in the FBI of every unit.
- My pure script ways, which requires you to have special loading script, to measure every unit height, and to write down long .h files.


- Using Spring's mass tags is much simpler.

- My way is alot more complex. But it allows you to have a transportation weight different from the mass the engine use for blowing units and other stuff. And my way works in TA. (But you abandonned AATA complelty, right?)

So, in short, have a look at the ArmDuck script from http://wormhole.tauniverse.com, and ask Wotan if you need explanation on how to use it (as I might have a tendancy to drown you into too much details).

And btw, the armduck script also showcase many other nifty scripting stuff that would fit well in that thread, and it's recent enough to have the lastest version of those script tricks. (For instance, I made many worse angle reading script before reaching the current form). I don't believe a bos without an accompagnying model, fbi, and whole unit is useable (because for instance you need to know where the pieces are to understand some bits of the script), and also 1600 BOS lines per post made thread unreadable, and many of the ArmDuck trick are for TA and useless/replacable by better stuff/don't work in Spring, but just to go with the flock:



/*========================================
Transport featuring auto-unload script:
- Automatic deployment of all loaded units when instructed to unload one.
- Deployment of units into three different formations, rectangle in front of transport when the unload cursor is in front, circles around transport when the unload cursor is in the back, squares around transport when the unload cursor is in the center.
- Detection of failed unload attempts due to invalid unload locations and increasing formation size when it occurs.
- Easily customiseable via lots of #define
- If a loaded unit has been stolen (by a regular air transport for instance), then it detects that and skips it.
- If asked to unload units while it believes it has 0 loaded units, then revert to manual one at a time unload. Useful to retrieve loaded units that haven't been registered, due to an abrupt killing of the script at the wrong moment, a savegame - modify unit - loadgame sequence, and things like that.
- Return before trying to unload out of the [100] or maybe [250] limit to prevent crashes => NO MORE CRASHES IN WATER!!
- Choice between animation of the units moving in and out or instantaneous load/unload. With or without explosions.
- Unit may be upright=1 to prevent units from being dropped sideway, scripted slope leaning to compensate.
- Slope leaning inhibited when the transport is transported or when over water.
- Take the ground height difference into account in loading and unloading trajectory.
- Script independent of unitlimit. But in return the loading is still manual.
- Attempt to determine unitlimit, so as to limit loading to units that belong to the same player.
- Abort auto unload if asked to move during the autounload sequence.
- Fully compatible with both TotalA and Spring. Well, save the only-load-player-units that isn't Spring compatible.
- Added use of H2WEIGHT.h, which make it possible to have some units take more cargo room than others. (Currently disabled, change LIMITED_CARGO_HOLD to enable)

Inspired from the SWTA transport script by Influenza with help from SOI Sentinel and Brave Sir Robin
Rewritten and improved by zwzsg

========================================*/



#define GROUP_UNLOAD 1
//#define GROUP_UNLOAD 0//--> no group unload, manual one-unit-per-click unload. For instance, in Spring there's already the zone unload, so you could set it to 0. But formations are neat even in Spring though.
//#define GROUP_UNLOAD 1//--> auto group unload in formation

#define LIMITED_CARGO_HOLD FALSE // Use the TCLASS list

#define LEAN_ON_SLOPE TRUE// To avoid kbots being dropped sideway, it's best to make the transport upright=1; and to enable that scripted slope leaning, but it remove the wobbling of hovercraft.

#define LOAD_ONLY_PLAYER_UNITS TRUE
// You can use that to prevent stealing of enemy units.
// When enabled, this script determine the unitlimit, by itself.
//
// This add the team thing. It checks the ID 1951, 1901, 1851... 51 to see if they are commanders, and if so, it suppose it's the commander of the second player and use that to calculate unitlimit. So:
// - if the unitlimit is not a multiple of 50
// - if the unitlimit is 2000 or higher
// - if the second player died
// - if the first player built commander decoy and your are unlucky (probability 1/50 per decoy)
// Then it gets confused and use a wrong unitlimit or can't find the unitlimit. However, save if decoys tricks it, it will uses then a higher unitlimit, so it can still load all player units, just also some or all enemy units. To solve the issue with decoys, well, if it's for a big mod like Absolute Annihilation, just modify the arm and core decoys 3do so are a bit taller.
// Normally, it shouldn't crash even if the unitlimit is as low as 200 like for unpatched TA 1.0. That's why I start at 1951 btw.
// Oh, and each transport hover determine the unitlimit at the time of his birth. So, let's say you build a hover, then player 2 comm dies, then you build another, the first one won't load enemy units but the second may. Well, it won't if you are player 1 and you try to load player 3 units, but will if you are player 3 and load player 4 units.
// Oh, and I haven't fully tested that team thing, so if it behave incorrecly, post a bug report more precise than you can.
// Oh, and I said team, but I meant units-belonging-to-same-player. As I said before, script can't really determine alliances in TA.

#define DECLARE_ALL_LOCAL_VARS_AT_BEGINNING TRUE // TA accept local variable to be declared anywhere, but for Spring they have to be declared at the beginning of function.


#include "sfxtype.h"
#include "exptype.h"
#define TA

piece base, hull, leftdoor, rightdoor,
turret, leftbarrel, leftflare, rightbarrel, rightflare,
wheel1, wheel2, wheel3, wheel4, wheel5, wheel6, wheel7, wheel8,
wake1, wake2, wake3, wake4, wake5, wake6, wake7, wake8,
load_shoulder, load_arm,
unload_shoulder, unload_arm,
goal_shoulder, goal_arm,
front, rear, left, right;

static-var is_moving, units_inside,
terrain_code, x_slope, z_slope,
DelayBeforeRestore, togglebarrel,
#if LOAD_ONLY_PLAYER_UNITS
self_id, units_per_player,
#endif
#if GROUP_UNLOAD
u1-2, u3-4, u5-6, u7-8, u9-10, u11-12, u13-14, u15-16, u17-18, u19-20, u21-22, u23-24, u25-26, u27-28, u29-30, u31-32, u33-34, u35-36, u37-38, u39-40, u41-42, u43-44, u45-46, u47-48, u49-50,
#endif
#if LIMITED_CARGO_HOLD
cargo_hold,
#endif
unused;
// I ain't totally sure of the maximum number of variables before they start overlapping. Hope this isn't over.

// Signal definitions:
#define SIG_PRIMARY 2
#define SIG_MOVE 32

#define AIM_VERTICALLY TRUE// set to TRUE to aim with pitch and not only with heading.// set to FALSE to aim only with heading and not with pitch.
#define MIN_MANPOWER_FOR_PRIMARY 1// Number of troops that must be in before the secondary weapon becomes unlocked

// The transport script values:

#define MAX_UNITS_INSIDE 50// Must not be higher than 50 for Group Unload

#define MAX_CARGO_HOLD 3000

#define INSTA_LOAD FALSE
#define INSTA_UNLOAD FALSE
#define EXPLODE_WHEN_LOADING FALSE
#define EXPLODE_WHEN_UNLOADING FALSE
#define FLAME_WHEN_LOADING FALSE
#define FLAME_WHEN_UNLOADING FALSE

#define QUIT_AUTO_UNLOAD_WHEN_MOVING TRUE
// Stop the autounload, but still finish trying to unload the current unit, when the transport starts moving. Also force the transport to wait till it's fully stopped before starting autounloading.
// I'm not 100% sure that part works flawlessly, so I would advise to let it FALSE unless you really want it:
// For instance if the transport turns without "moving", it might keeps on unloading, or if the auto-unloading abortion occurs while it's trying to unload on unfit place the unit being currently unloaded might not be correctly re-registered as in and so won't be unloaded during next auto-unloaded and you'll have to click unload once more to retrieve it.

#define DISAPPEAR_RADIUS [10]// Must not be null. Radius under which the unit is so close it's in, radius under which the unit stops being shown over the transport
#define TOLERANCE [1]// Tolerance when checking if a unit is at the same position than a piece because when the transport is moving, any attached unit update its position with a small delay, resulting in the attached unit being a couple pixel away from the piece it is attached to.

#define LOAD_MAXIMUM_RADIUS [120]// Over around [100], risk of crashing TotalA.exe, but actually it seems that for attached units the limit is higher.
#define LOAD_SPEED [80]

#define MANUAL_UNLOAD_MAXIMUM_RADIUS [95]// Over around [100], risk of crashing TotalA.exe, but actually it seems that for attached units the limit is higher.
#define MANUAL_UNLOAD_SPEED [120]
#define MANUAL_UNLOAD_MINIMUM_RADIUS [20]// If the unload radius is too small, it will be upped to this

#define AUTO_UNLOAD_MAX_DISTANCE_BEFORE_STARTING [85]// Set to [85] which is the same value as XTA Spring ArmTHovr because Spring is harcoded to stop at that distance to target before unloading
#define AUTO_UNLOAD_MAXIMUM_RADIUS [180]// Over around [100], risk of crashing TotalA.exe, but actually it seems that for attached units the limit is higher.
#define AUTO_UNLOAD_DISTANCE_FIRST_ROW [27]
#define AUTO_UNLOAD_SIDE_SPACING [20]
#define AUTO_UNLOAD_FRONT_SPACING [20]
#define AUTO_UNLOAD_UNITS_PER_ROW 5 // Only used in shape==2, which anyway is rendered obsolete now by the better shape==1
#define AUTO_UNLOAD_SPEED [60]
#define AUTO_UNLOAD_SQUARE_CORRECTION_ANGULAR_SPEED <60>
#define AUTO_UNLOAD_CIRCLE_CORRECTION_ANGULAR_SPEED <240>
#define AUTO_UNLOAD_FIRST_RADIUS [30]
#define AUTO_UNLOAD_RADIUS_INCREMENT [20]
#define AUTO_UNLOAD_ARC_LENGTH [18]
#define AUTO_UNLOAD_RADIAL_PROPORTION 2/3 // Fractionnal Exceptionnaly Allowed, from 0 (full frontward), to 1 (full radial)
#define AUTO_UNLOAD_FIRST_ROW 2// integer, not distance
#define AUTO_UNLOAD_SIDE_INCREMENT [20]
#define AUTO_UNLOAD_SR_PROPORTION 1/(-8) // Fractionnal Exceptionnaly Allowed, from 0 (full frontward), to 1 (full radial)
#define PIECE_TO_EXPLODE_WHEN_IT_GOES_WRONG hull

// Currently, it takes, for 50 units:
// Complete loading sequence: s
// Comple square auto-unloading sequence s
// Comple circles auto-unloading sequence s




// The transport script macros:

#define OPENING_DOOR_ANIMATION \
turn leftdoor to z-axis <150> now; \
turn rightdoor to z-axis 0- <150> now;

#define CLOSING_DOOR_ANIMATION \
turn leftdoor to z-axis <0> speed <60>; \
turn rightdoor to z-axis <00> speed <60>;

#if LIMITED_CARGO_HOLD
#include "H2WEIGHT.h"
#endif

#if GROUP_UNLOAD

#if MAX_UNITS_INSIDE>50
#WeSaidNoMoreThanFifty// Purposefully cause Scriptor to error
#endif

#define INIT_LOADED_ID(value_at_which_init) \
u49-50=value_at_which_init; \
u47-48=value_at_which_init; \
u45-46=value_at_which_init; \
u43-44=value_at_which_init; \
u41-42=value_at_which_init; \
u39-40=value_at_which_init; \
u37-38=value_at_which_init; \
u35-36=value_at_which_init; \
u33-34=value_at_which_init; \
u31-32=value_at_which_init; \
u29-30=value_at_which_init; \
u27-28=value_at_which_init; \
u25-26=value_at_which_init; \
u23-24=value_at_which_init; \
u21-22=value_at_which_init; \
u19-20=value_at_which_init; \
u17-18=value_at_which_init; \
u15-16=value_at_which_init; \
u13-14=value_at_which_init; \
u11-12=value_at_which_init; \
u9-10=value_at_which_init; \
u7-8=value_at_which_init; \
u5-6=value_at_which_init; \
u3-4=value_at_which_init; \
u1-2=value_at_which_init;


#define STORE_LOADED_ID(unit_to_store) \
if(units_inside==50) \
{u49-50=(u49-50 - (u49-50/65536)*65536) + unit_to_store*65536;} \
if(units_inside==49) \
{u49-50=(u49-50/65536)*65536 + unit_to_store;} \
if(units_inside==48) \
{u47-48=(u47-48 - (u47-48/65536)*65536) + unit_to_store*65536;} \
if(units_inside==47) \
{u47-48=(u47-48/65536)*65536 + unit_to_store;} \
if(units_inside==46) \
{u45-46=(u45-46 - (u45-46/65536)*65536) + unit_to_store*65536;} \
if(units_inside==45) \
{u45-46=(u45-46/65536)*65536 + unit_to_store;} \
if(units_inside==44) \
{u43-44=(u43-44 - (u43-44/65536)*65536) + unit_to_store*65536;} \
if(units_inside==43) \
{u43-44=(u43-44/65536)*65536 + unit_to_store;} \
if(units_inside==42) \
{u41-42=(u41-42 - (u41-42/65536)*65536) + unit_to_store*65536;} \
if(units_inside==41) \
{u41-42=(u41-42/65536)*65536 + unit_to_store;} \
if(units_inside==40) \
{u39-40=(u39-40 - (u39-40/65536)*65536) + unit_to_store*65536;} \
if(units_inside==39) \
{u39-40=(u39-40/65536)*65536 + unit_to_store;} \
if(units_inside==38) \
{u37-38=(u37-38 - (u37-38/65536)*65536) + unit_to_store*65536;} \
if(units_inside==37) \
{u37-38=(u37-38/65536)*65536 + unit_to_store;} \
if(units_inside==36) \
{u35-36=(u35-36 - (u35-36/65536)*65536) + unit_to_store*65536;} \
if(units_inside==35) \
{u35-36=(u35-36/65536)*65536 + unit_to_store;} \
if(units_inside==34) \
{u33-34=(u33-34 - (u33-34/65536)*65536) + unit_to_store*65536;} \
if(units_inside==33) \
{u33-34=(u33-34/65536)*65536 + unit_to_store;} \
if(units_inside==32) \
{u31-32=(u31-32 - (u31-32/65536)*65536) + unit_to_store*65536;} \
if(units_inside==31) \
{u31-32=(u31-32/65536)*65536 + unit_to_store;} \
if(units_inside==30) \
{u29-30=(u29-30 - (u29-30/65536)*65536) + unit_to_store*65536;} \
if(units_inside==29) \
{u29-30=(u29-30/65536)*65536 + unit_to_store;} \
if(units_inside==28) \
{u27-28=(u27-28 - (u27-28/65536)*65536) + unit_to_store*65536;} \
if(units_inside==27) \
{u27-28=(u27-28/65536)*65536 + unit_to_store;} \
if(units_inside==26) \
{u25-26=(u25-26 - (u25-26/65536)*65536) + unit_to_store*65536;} \
if(units_inside==25) \
{u25-26=(u25-26/65536)*65536 + unit_to_store;} \
if(units_inside==24) \
{u23-24=(u23-24 - (u23-24/65536)*65536) + unit_to_store*65536;} \
if(units_inside==23) \
{u23-24=(u23-24/65536)*65536 + unit_to_store;} \
if(units_inside==22) \
{u21-22=(u21-22 - (u21-22/65536)*65536) + unit_to_store*65536;} \
if(units_inside==21) \
{u21-22=(u21-22/65536)*65536 + unit_to_store;} \
if(units_inside==20) \
{u19-20=(u19-20 - (u19-20/65536)*65536) + unit_to_store*65536;} \
if(units_inside==19) \
{u19-20=(u19-20/65536)*65536 + unit_to_store;} \
if(units_inside==18) \
{u17-18=(u17-18 - (u17-18/65536)*65536) + unit_to_store*65536;} \
if(units_inside==17) \
{u17-18=(u17-18/65536)*65536 + unit_to_store;} \
if(units_inside==16) \
{u15-16=(u15-16 - (u15-16/65536)*65536) + unit_to_store*65536;} \
if(units_inside==15) \
{u15-16=(u15-16/65536)*65536 + unit_to_store;} \
if(units_inside==14) \
{u13-14=(u13-14 - (u13-14/65536)*65536) + unit_to_store*65536;} \
if(units_inside==13) \
{u13-14=(u13-14/65536)*65536 + unit_to_store;} \
if(units_inside==12) \
{u11-12=(u11-12 - (u11-12/65536)*65536) + unit_to_store*65536;} \
if(units_inside==11) \
{u11-12=(u11-12/65536)*65536 + unit_to_store;} \
if(units_inside==10) \
{u9-10=(u9-10 - (u9-10/65536)*65536) + unit_to_store*65536;} \
if(units_inside==9) \
{u9-10=(u9-10/65536)*65536 + unit_to_store;} \
if(units_inside==8) \
{u7-8=(u7-8 - (u7-8/65536)*65536) + unit_to_store*65536;} \
if(units_inside==7) \
{u7-8=(u7-8/65536)*65536 + unit_to_store;} \
if(units_inside==6) \
{u5-6=(u5-6 - (u5-6/65536)*65536) + unit_to_store*65536;} \
if(units_inside==5) \
{u5-6=(u5-6/65536)*65536 + unit_to_store;} \
if(units_inside==4) \
{u3-4=(u3-4 - (u3-4/65536)*65536) + unit_to_store*65536;} \
if(units_inside==3) \
{u3-4=(u3-4/65536)*65536 + unit_to_store;} \
if(units_inside==2) \
{u1-2=(u1-2 - (u1-2/65536)*65536) + unit_to_store*65536;} \
if(units_inside==1) \
{u1-2=(u1-2/65536)*65536 + unit_to_store;} \
if(units_inside<=0 || units_inside>MAX_UNITS_INSIDE) \
{ \
explode PIECE_TO_EXPLODE_WHEN_IT_GOES_WRONG type SHATTER | BITMAP2; \
show PIECE_TO_EXPLODE_WHEN_IT_GOES_WRONG; \
}


#define GET_ID_TO_UNLOAD(unit_to_retrieve) \
if(units_inside==50) \
{unit_to_retrieve=(u49-50)/65536;} \
if(units_inside==49) \
{unit_to_retrieve=(u49-50 - (u49-50/65536)*65536);} \
if(units_inside==48) \
{unit_to_retrieve=(u47-48)/65536;} \
if(units_inside==47) \
{unit_to_retrieve=(u47-48 - (u47-48/65536)*65536);} \
if(units_inside==46) \
{unit_to_retrieve=(u45-46)/65536;} \
if(units_inside==45) \
{unit_to_retrieve=(u45-46 - (u45-46/65536)*65536);} \
if(units_inside==44) \
{unit_to_retrieve=(u43-44)/65536;} \
if(units_inside==43) \
{unit_to_retrieve=(u43-44 - (u43-44/65536)*65536);} \
if(units_inside==42) \
{unit_to_retrieve=(u41-42)/65536;} \
if(units_inside==41) \
{unit_to_retrieve=(u41-42 - (u41-42/65536)*65536);} \
if(units_inside==40) \
{unit_to_retrieve=(u39-40)/65536;} \
if(units_inside==39) \
{unit_to_retrieve=(u39-40 - (u39-40/65536)*65536);} \
if(units_inside==38) \
{unit_to_retrieve=(u37-38)/65536;} \
if(units_inside==37) \
{unit_to_retrieve=(u37-38 - (u37-38/65536)*65536);} \
if(units_inside==36) \
{unit_to_retrieve=(u35-36)/65536;} \
if(units_inside==35) \
{unit_to_retrieve=(u35-36 - (u35-36/65536)*65536);} \
if(units_inside==34) \
{unit_to_retrieve=(u33-34)/65536;} \
if(units_inside==33) \
{unit_to_retrieve=(u33-34 - (u33-34/65536)*65536);} \
if(units_inside==32) \
{unit_to_retrieve=(u31-32)/65536;} \
if(units_inside==31) \
{unit_to_retrieve=(u31-32 - (u31-32/65536)*65536);} \
if(units_inside==30) \
{unit_to_retrieve=(u29-30)/65536;} \
if(units_inside==29) \
{unit_to_retrieve=(u29-30 - (u29-30/65536)*65536);} \
if(units_inside==28) \
{unit_to_retrieve=(u27-28)/65536;} \
if(units_inside==27) \
{unit_to_retrieve=(u27-28 - (u27-28/65536)*65536);} \
if(units_inside==26) \
{unit_to_retrieve=(u25-26)/65536;} \
if(units_inside==25) \
{unit_to_retrieve=(u25-26 - (u25-26/65536)*65536);} \
if(units_inside==24) \
{unit_to_retrieve=(u23-24)/65536;} \
if(units_inside==23) \
{unit_to_retrieve=(u23-24 - (u23-24/65536)*65536);} \
if(units_inside==22) \
{unit_to_retrieve=(u21-22)/65536;} \
if(units_inside==21) \
{unit_to_retrieve=(u21-22 - (u21-22/65536)*65536);} \
if(units_inside==20) \
{unit_to_retrieve=(u19-20)/65536;} \
if(units_inside==19) \
{unit_to_retrieve=(u19-20 - (u19-20/65536)*65536);} \
if(units_inside==18) \
{unit_to_retrieve=(u17-18)/65536;} \
if(units_inside==17) \
{unit_to_retrieve=(u17-18 - (u17-18/65536)*65536);} \
if(units_inside==16) \
{unit_to_retrieve=(u15-16)/65536;} \
if(units_inside==15) \
{unit_to_retrieve=(u15-16 - (u15-16/65536)*65536);} \
if(units_inside==14) \
{unit_to_retrieve=(u13-14)/65536;} \
if(units_inside==13) \
{unit_to_retrieve=(u13-14 - (u13-14/65536)*65536);} \
if(units_inside==12) \
{unit_to_retrieve=(u11-12)/65536;} \
if(units_inside==11) \
{unit_to_retrieve=(u11-12 - (u11-12/65536)*65536);} \
if(units_inside==10) \
{unit_to_retrieve=(u9-10)/65536;} \
if(units_inside==9) \
{unit_to_retrieve=(u9-10 - (u9-10/65536)*65536);} \
if(units_inside==8) \
{unit_to_retrieve=(u7-8)/65536;} \
if(units_inside==7) \
{unit_to_retrieve=(u7-8 - (u7-8/65536)*65536);} \
if(units_inside==6) \
{unit_to_retrieve=(u5-6)/65536;} \
if(units_inside==5) \
{unit_to_retrieve=(u5-6 - (u5-6/65536)*65536);} \
if(units_inside==4) \
{unit_to_retrieve=(u3-4)/65536;} \
if(units_inside==3) \
{unit_to_retrieve=(u3-4 - (u3-4/65536)*65536);} \
if(units_inside==2) \
{unit_to_retrieve=(u1-2)/65536;} \
if(units_inside==1) \
{unit_to_retrieve=(u1-2 - (u1-2/65536)*65536);} \
if(units_inside<=0 || units_inside>MAX_UNITS_INSIDE) \
{ \
explode PIECE_TO_EXPLODE_WHEN_IT_GOES_WRONG type SHATTER | BITMAP2; \
show PIECE_TO_EXPLODE_WHEN_IT_GOES_WRONG; \
CLOSING_DOOR_ANIMATION \
set BUSY to 0; \
return; \
}

#else // so, if NOT GROUP_UNLOAD

#define INIT_LOADED_ID(value_at_which_init)
#define STORE_LOADED_ID(unit_to_store)
#define GET_ID_TO_UNLOAD(unit_to_retrieve)

#endif // end if GROUP_UNLOAD



TransportPickup(unit_to_load)
{
#if LIMITED_CARGO_HOLD
var h,w;
#endif
if(get XZ_HYPOT(get UNIT_XZ(unit_to_load) - get PIECE_XZ(load_shoulder))<=LOAD_MAXIMUM_RADIUS)
{
set BUSY to 1;
if(units_inside<0)
{
units_inside=0;
#if LIMITED_CARGO_HOLD
cargo_hold=0;
#endif
}
#if GROUP_UNLOAD
if(units_inside>=MAX_UNITS_INSIDE)//For some odd reason, when shift-enqueing "load" orders, it sometimes catch one more unit than the transportcapacity value defined in the unit FBI. You can remove that part and see, it's harmless: The part that store the ID won't be able to store it so will show some explosion, the part that unload will see it's an unstored ID and so will use manual unload for fist unit.
{
sleep 320;
set BUSY to 0;
return;
}
#endif
#if LOAD_ONLY_PLAYER_UNITS
if ((unit_to_load - 1)/units_per_player!=(self_ID - 1)/units_per_player)
{
sleep 320;
set BUSY to 0;
return;
}
#endif
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_load);
CALC_WEIGHT;
if(cargo_hold + w>MAX_CARGO_HOLD)
{
sleep 320;
set BUSY to 0;
return;
}
#endif
OPENING_DOOR_ANIMATION
#if ((!INSTA_LOAD) || (EXPLODE_WHEN_LOADING) || (FLAME_WHEN_LOADING))
turn load_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(load_shoulder) - get UNIT_XZ(unit_to_load)) now;
move load_arm to z-axis get XZ_HYPOT(get UNIT_XZ(unit_to_load) - get PIECE_XZ(load_shoulder)) now;
move load_arm to y-axis get GROUND_HEIGHT(get UNIT_XZ(unit_to_load)) - get PIECE_Y(load_shoulder) now;
#endif
#if EXPLODE_WHEN_LOADING
explode load_arm type BITMAPONLY | BITMAP2;
#endif
#if FLAME_WHEN_LOADING
emit-sfx SFXTYPE_VTOL from load_arm;
#endif
#if !INSTA_LOAD
turn load_arm to y-axis get XZ_ATAN(get UNIT_XZ(unit_to_load) - get PIECE_XZ(load_shoulder)) now;
attach-unit unit_to_load to load_arm;
move load_arm to z-axis DISAPPEAR_RADIUS speed LOAD_SPEED;
move load_arm to y-axis 0 speed (1 - 2*(get GROUND_HEIGHT(get UNIT_XZ(unit_to_load)) < get PIECE_Y(load_shoulder)))*(((((get GROUND_HEIGHT(get UNIT_XZ(unit_to_load)) - get PIECE_Y(load_shoulder))*48) / get XZ_HYPOT(get PIECE_XZ(load_shoulder) - get UNIT_XZ(unit_to_load))) * LOAD_SPEED)/48);// K, have fun deciphering this one!
wait-for-move load_arm along z-axis;
#endif
attach-unit unit_to_load to 0 - 1;
++units_inside;
#if LIMITED_CARGO_HOLD
cargo_hold=cargo_hold + w;
#endif
STORE_LOADED_ID(unit_to_load)
CLOSING_DOOR_ANIMATION
set BUSY to 0;
}
}



TransportDrop(unit_to_manual_unload, position_to_manual_unload)
{
#if DECLARE_ALL_LOCAL_VARS_AT_BEGINNING

#if LIMITED_CARGO_HOLD
var h, w, val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11;
#else
var val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11;
#endif

#define distance_to_wanted_manual_unload_position val1

#define unit_to_auto_unload val1
#define z_to_unload val2
#define x_to_unload val3
#define pos_on_row val4
#define num_row val5
#define radius_to_unload val2
#define angle_to_unload val3
#define pos_on_circle val4
#define num_circle val5
#define max_pos val6
#define same val7
#define last_goal val8
#define shape val9
// because h and w are used in a macro #defined inside the H2WEIGHT.h that is #included at the very beginning, h and w can't be #defined but have to be declared

#else

#if LIMITED_CARGO_HOLD
var h,w;
#endif

#endif

#if (GROUP_UNLOAD==1)
if(units_inside<=0 || units_inside>MAX_UNITS_INSIDE)// If manual unload or if unit to unload unregistered
{
#endif
// Manual Unload:
#if !DECLARE_ALL_LOCAL_VARS_AT_BEGINNING
var distance_to_wanted_manual_unload_position;
#endif
distance_to_wanted_manual_unload_position=get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - position_to_manual_unload);
if(distance_to_wanted_manual_unload_position<MANUAL_UNLOAD_MINIMUM_RADIUS)
{
distance_to_wanted_manual_unload_position=MANUAL_UNLOAD_MINIMUM_RADIUS;
}
if(distance_to_wanted_manual_unload_position<=MANUAL_UNLOAD_MAXIMUM_RADIUS)
{
set BUSY to 1;
OPENING_DOOR_ANIMATION
turn unload_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - position_to_manual_unload) now;
move unload_arm to x-axis 0 now;
move unload_arm to y-axis 0 now;
#if !INSTA_UNLOAD
move unload_arm to z-axis DISAPPEAR_RADIUS now;
#endif
turn unload_arm to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - position_to_manual_unload) now;
#if !INSTA_UNLOAD
attach-unit unit_to_manual_unload to unload_arm;
move unload_arm to z-axis distance_to_wanted_manual_unload_position speed MANUAL_UNLOAD_SPEED;
move unload_arm to y-axis get GROUND_HEIGHT(position_to_manual_unload) - get PIECE_Y(unload_shoulder) speed (1 - 2*(get GROUND_HEIGHT(position_to_manual_unload) < get PIECE_Y(unload_shoulder)))*(((((get GROUND_HEIGHT(position_to_manual_unload) - get PIECE_Y(unload_shoulder))*48) / get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - position_to_manual_unload)) * MANUAL_UNLOAD_SPEED)/48);// K, have fun deciphering this one!
#endif
#if INSTA_UNLOAD// hash-if !VALUE ... hash-else makes Scriptor fails. And hash-if in comments are counted!
move unload_arm to z-axis distance_to_wanted_manual_unload_position now;
move unload_arm to y-axis get GROUND_HEIGHT(position_to_manual_unload) - get PIECE_Y(unload_shoulder) now;
attach-unit unit_to_manual_unload to unload_arm;
#endif
wait-for-move unload_arm along z-axis;
drop-unit unit_to_manual_unload;
--units_inside;
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_manual_unload);
CALC_WEIGHT;
cargo_hold=cargo_hold - w;
#endif
#if !INSTA_UNLOAD
sleep 1;
#endif
move unload_arm to z-axis 0 now;
move unload_arm to y-axis 0 now;
sleep 1;//wait-for-move unload_arm along z-axis;
if(get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get UNIT_XZ(unit_to_manual_unload))<=TOLERANCE)//If it failed dropping
{
attach-unit unit_to_manual_unload to 0 - 1;
++units_inside;
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_manual_unload);
CALC_WEIGHT;
cargo_hold=cargo_hold + w;
#endif
}
#if ((EXPLODE_WHEN_UNLOADING) || (FLAME_WHEN_UNLOADING))
if(!(get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get UNIT_XZ(unit_to_manual_unload))<=TOLERANCE))//If it succeed dropping
{
move unload_arm to z-axis distance_to_wanted_manual_unload_position now;
move unload_arm to y-axis get GROUND_HEIGHT(position_to_manual_unload) - get PIECE_Y(unload_shoulder) now;
#if EXPLODE_WHEN_UNLOADING
explode unload_arm type BITMAPONLY | BITMAP2;
#endif
#if FLAME_WHEN_UNLOADING
emit-sfx SFXTYPE_VTOL from unload_arm;
#endif
move unload_arm to z-axis 0 now;
move unload_arm to y-axis 0 now;
}
#endif
#if !INSTA_UNLOAD
sleep 100;
#endif
CLOSING_DOOR_ANIMATION
set BUSY to 0;
}
#if GROUP_UNLOAD
return;
}// end Manual Unload



// Auto Unload:

#if !DECLARE_ALL_LOCAL_VARS_AT_BEGINNING
var unit_to_auto_unload, val1, val2, val3, val4, val5, same, last_goal, shape;
#define z_to_unload val1
#define x_to_unload val2
#define pos_on_row val3
#define num_row val4
#define radius_to_unload val1
#define angle_to_unload val2
#define pos_on_circle val3
#define num_circle val4
#define max_pos val5
// those define were so rectangular and multi circular use the same variables but under different names, because there is a limit to the number of local variable there can be in a TA script
#endif

if(get XZ_HYPOT(get PIECE_XZ(base) - position_to_manual_unload)>AUTO_UNLOAD_MAX_DISTANCE_BEFORE_STARTING)
{
sleep 120;
return;
}

//shape=(get XZ_HYPOT(get PIECE_XZ(base) - position_to_manual_unload)>[8]) && ((((get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)>0 - 16384) && (get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)< 16384)) || (get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)> 49152)));
shape=(get XZ_HYPOT(get PIECE_XZ(base) - position_to_manual_unload)>[8])*(((((get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)>0 - 16384) && (get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)< 16384)) || (get XZ_ATAN(get PIECE_XZ(base) - position_to_manual_unload)> 49152)))-3)+3;
//
// The variable shape determine the shape of the formation. It can only be 0,1, or 2.
// The currrent formula makes it uses shape 0 when clicking behind, shape 1 when clicking in front, and shape 3 when clicking center. The current formula doesn't use shape 2, as I feel shape 1 is like shape 2 but much better.
//
// Shape==0 Shape==1 Shape==2 Shape==3
// ooo
// oxxxo +++++++++ +++++ ooooooo
// ox213xo +ooooooo+ ooooo oxxxxxo
// ox4 5xo +oxxxxxo+ xxxxx ox213xo
// ox6 7xo +ox546xo+ 97680 ox405xo
// ox809xo +ox213xo+ 42135 ox687xo
// oxxxo oxxxxxo
// ooo ooooooo

set BUSY to 1;
OPENING_DOOR_ANIMATION
#if QUIT_AUTO_UNLOAD_WHEN_MOVING
while(is_moving)
{
sleep 100;
}
#endif

if(shape==0)
{
num_circle=0;
pos_on_circle=0;
same=FALSE;
}

if(shape==1)
{
num_row=0;
pos_on_row=0;
same=FALSE;
}

if(shape==2)
{
num_row=0;
pos_on_row=0;
same=FALSE;
}

if(shape==3)
{
num_row=AUTO_UNLOAD_FIRST_ROW;
pos_on_row=0;
same=FALSE;
}

while(units_inside>0)
{
if(shape==0)
{
radius_to_unload=(AUTO_UNLOAD_FIRST_RADIUS) + (num_circle * (AUTO_UNLOAD_RADIUS_INCREMENT));
max_pos=(((radius_to_unload/1000)*6283)/AUTO_UNLOAD_ARC_LENGTH);// This is tricky: we must not go over 2^31, yet we must always have numbers much greater than 1 (otherwise decimals are lost)
angle_to_unload=((pos_on_circle+1)/2)*65536/max_pos;
// max_number_of_pos_per_circle = radius*2pi/ arc_between_each_pos
// angle to unload = (half-position / max_number_of_pos_per_circle) * angle_of_full_turn
// half position because each even numbered pos is the same as the odd one just with a minus sign
// and multiplication before division to avoid losing the decimal since scripts can only handle integers
// and +1 to pos so pos 0 and pos 1 aren't on same null angle but only 0 is
if(((pos_on_circle/2)*2)==pos_on_circle)
{
angle_to_unload=0 - angle_to_unload;
}
if(((num_circle/2)*2)!=num_circle)
{
angle_to_unload=angle_to_unload - 32768/max_pos;
}
turn goal_shoulder to y-axis angle_to_unload now;
move goal_arm to z-axis radius_to_unload now;
move goal_arm to x-axis 0 now;
}
if(shape==1)
{
// +++++++++
// +LJHGIKM+
// +ExxxxxF+
// +Cx546xD+
// +Ax213xB+
if(pos_on_row<2*num_row)
{
z_to_unload=((pos_on_row/2)*AUTO_UNLOAD_FRONT_SPACING)+AUTO_UNLOAD_DISTANCE_FIRST_ROW;
x_to_unload=((2*(((pos_on_row+1)/2)==((pos_on_row+2)/2))-1)*num_row)*AUTO_UNLOAD_SIDE_SPACING;
}
if(pos_on_row>=2*num_row)
{
z_to_unload=(num_row * (AUTO_UNLOAD_FRONT_SPACING))+AUTO_UNLOAD_DISTANCE_FIRST_ROW;
x_to_unload=(2*(((pos_on_row+1)/2)==((pos_on_row+2)/2))-1)*((pos_on_row +1 - 2*num_row)/2)*AUTO_UNLOAD_SIDE_SPACING;
}
turn goal_shoulder to y-axis 0 now;
move goal_arm to z-axis z_to_unload now;
move goal_arm to x-axis x_to_unload now;
}
if(shape==2)
{
z_to_unload=(AUTO_UNLOAD_DISTANCE_FIRST_ROW) + (num_row * (AUTO_UNLOAD_FRONT_SPACING));
x_to_unload=((1+pos_on_row)/2)*AUTO_UNLOAD_SIDE_SPACING;
if(((pos_on_row/2)*2)!=pos_on_row)
{
x_to_unload=0 - x_to_unload;
}
if((AUTO_UNLOAD_UNITS_PER_ROW/2)*2==AUTO_UNLOAD_UNITS_PER_ROW)
{
x_to_unload=x_to_unload + AUTO_UNLOAD_SIDE_SPACING/2;
}
turn goal_shoulder to y-axis 0 now;
move goal_arm to z-axis z_to_unload now;
move goal_arm to x-axis x_to_unload now;
}
if(shape==3)
{
// num_row = number of the onion ring
// num_row = 0 -> the first ring, with 1 spot
// num_row = 1 -> the first ring, with 8 spot
// num_row = 2 -> the first ring, with 16 spot
// num_row = 3 -> the first ring, with 24 spot
//
// pos_on_row = from 0 to max_pos, reset to 0 at each row
//
// max_pos= 0, 7, 15,23, ...
//
max_pos=8*num_row - (num_row!=0);
if(pos_on_row<=(num_row*2))// The front line, including corners
{
z_to_unload=num_row * AUTO_UNLOAD_SIDE_INCREMENT;
x_to_unload=(1-2*((pos_on_row/2)*2==pos_on_row))*((pos_on_row+1)/2)* AUTO_UNLOAD_SIDE_INCREMENT;
}
if((pos_on_row>(num_row*2)) && (pos_on_row<6*num_row -1))// The two side lines, excluding corners
{
z_to_unload=(2*num_row -((pos_on_row+1)/2))*AUTO_UNLOAD_SIDE_INCREMENT;
x_to_unload=(1-2*((pos_on_row/2)*2==pos_on_row))*(num_row* AUTO_UNLOAD_SIDE_INCREMENT);
}
if(pos_on_row>=6*num_row -1)// The back line, including corners
{
z_to_unload= 0 - num_row * AUTO_UNLOAD_SIDE_INCREMENT;
x_to_unload=(1-2*((pos_on_row/2)*2==pos_on_row))*((pos_on_row - 8*num_row)/2)* AUTO_UNLOAD_SIDE_INCREMENT;
}
turn goal_shoulder to y-axis 0 now;
move goal_arm to z-axis z_to_unload now;
move goal_arm to x-axis x_to_unload now;
}

if(get XZ_HYPOT(get PIECE_XZ(base) - get PIECE_XZ(goal_arm))>AUTO_UNLOAD_MAXIMUM_RADIUS)
{
// The goal is too far and TotalA.exe risk crashing if we move an attached unit there
CLOSING_DOOR_ANIMATION
set BUSY to 1;
sleep 2000;
set BUSY to 0;
return;
}
#if !INSTA_UNLOAD
turn unload_shoulder to y-axis 0 now;
move unload_arm to x-axis 0 now;
move unload_arm to y-axis 0 now;
move unload_arm to z-axis 0 now;
turn unload_arm to y-axis 0 now;
wait-for-move unload_arm along z-axis;
#endif

GET_ID_TO_UNLOAD(unit_to_auto_unload)
while((get XZ_HYPOT(get PIECE_XZ(base) - get UNIT_XZ(unit_to_auto_unload))>TOLERANCE) && (get XZ_HYPOT(get PIECE_XZ(load_shoulder) - get UNIT_XZ(unit_to_auto_unload))>TOLERANCE) && (get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get UNIT_XZ(unit_to_auto_unload))>TOLERANCE))// If the unit we got the ID of has been stolen, then get the next ID
{
--units_inside;
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_auto_unload);
CALC_WEIGHT;
cargo_hold=cargo_hold - w;
#endif
if(units_inside<=0)
{
CLOSING_DOOR_ANIMATION
set BUSY to 0;
return;
}
GET_ID_TO_UNLOAD(unit_to_auto_unload)
}
#if !INSTA_UNLOAD
if(!same)
{
turn unload_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) now;
move unload_arm to x-axis 0 now;
move unload_arm to y-axis 0 now;
move unload_arm to z-axis DISAPPEAR_RADIUS now;
turn unload_arm to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) now;
}
if(same)
{
turn unload_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - last_goal) now;
move unload_arm to x-axis 0 now;
move unload_arm to z-axis get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - last_goal) now;
move unload_arm to y-axis get GROUND_HEIGHT(last_goal) - get PIECE_Y(unload_shoulder) now;;
turn unload_arm to y-axis get XZ_ATAN(last_goal - get PIECE_XZ(goal_arm)) now;
wait-for-move unload_arm along z-axis;
attach-unit unit_to_auto_unload to unload_arm;
turn unload_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) speed (shape!=0)*(AUTO_UNLOAD_SQUARE_CORRECTION_ANGULAR_SPEED)+(shape==0)*(AUTO_UNLOAD_CIRCLE_CORRECTION_ANGULAR_SPEED);
wait-for-turn unload_shoulder around y-axis;
}
last_goal=get PIECE_XZ(goal_arm);

attach-unit unit_to_auto_unload to unload_arm;
sleep 1;
if (get XZ_HYPOT(get UNIT_XZ(unit_to_auto_unload) - get PIECE_XZ(base))>TOLERANCE)// If it is not the transport itself
{
move unload_arm to z-axis get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) speed AUTO_UNLOAD_SPEED;
move unload_arm to y-axis get GROUND_HEIGHT(get PIECE_XZ(goal_arm)) - get PIECE_Y(unload_shoulder) speed (1 - 2*(get GROUND_HEIGHT(get PIECE_XZ(goal_arm)) < get PIECE_Y(unload_shoulder)))*(((((get GROUND_HEIGHT(get PIECE_XZ(goal_arm)) - get PIECE_Y(unload_shoulder))*48) / get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))) * AUTO_UNLOAD_SPEED)/48);// K, have fun deciphering this one!
wait-for-move unload_arm along z-axis;
turn unload_arm to y-axis 0 now;
if(shape==0)
{
turn unload_arm to y-axis (get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))<32768)*(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))*AUTO_UNLOAD_RADIAL_PROPORTION)+(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))>=32768)*((get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) - 65536)*AUTO_UNLOAD_RADIAL_PROPORTION) now;
if (pos_on_circle==max_pos - 1)
{
turn unload_arm to y-axis 32768*((32768*AUTO_UNLOAD_RADIAL_PROPORTION>=16384) || (32768*AUTO_UNLOAD_RADIAL_PROPORTION<=0 - 16384)) now;
}
}
if(shape==3)
{
turn unload_arm to y-axis (get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))<32768)*(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))*AUTO_UNLOAD_SR_PROPORTION)+(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))>=32768)*((get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) - 65536)*AUTO_UNLOAD_SR_PROPORTION) now;
if (pos_on_circle==max_pos)
{
turn unload_arm to y-axis 32768*((32768*AUTO_UNLOAD_SR_PROPORTION>=16384) || (32768*AUTO_UNLOAD_SR_PROPORTION<=0 - 16384)) now;
}
}
wait-for-turn unload_arm around y-axis;
#endif
#if INSTA_UNLOAD// hash-if !VALUE ... hash-else makes Scriptor fails. And hash-if in comments are counted!
turn unload_shoulder to y-axis get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) now;
move unload_arm to x-axis 0 now;
move unload_arm to y-axis get GROUND_HEIGHT(get PIECE_XZ(goal_arm)) - get PIECE_Y(unload_shoulder) now;
move unload_arm to z-axis get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) now;
turn unload_arm to y-axis 0 now;
if(shape==0)
{
turn unload_arm to y-axis (get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))<32768)*(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))*AUTO_UNLOAD_RADIAL_PROPORTION)+(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))>=32768)*((get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) - 65536)*AUTO_UNLOAD_RADIAL_PROPORTION) now;
if (pos_on_circle==max_pos - 1)
{
turn unload_arm to y-axis 32768*((32768*AUTO_UNLOAD_RADIAL_PROPORTION>=16384) || (32768*AUTO_UNLOAD_RADIAL_PROPORTION<=0 - 16384)) now;
}
}
if(shape==3)
{
turn unload_arm to y-axis (get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))<32768)*(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))*AUTO_UNLOAD_SR_PROPORTION)+(get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm))>=32768)*((get XZ_ATAN(get PIECE_XZ(unload_shoulder) - get PIECE_XZ(goal_arm)) - 65536)*AUTO_UNLOAD_SR_PROPORTION) now;
if (pos_on_row==max_pos)
{
turn unload_arm to y-axis 32768*((32768*AUTO_UNLOAD_SR_PROPORTION>=16384) || (32768*AUTO_UNLOAD_SR_PROPORTION<=0 - 16384)) now;
}
}
attach-unit unit_to_auto_unload to unload_arm;
sleep 1;
if (get XZ_HYPOT(get UNIT_XZ(unit_to_auto_unload) - get PIECE_XZ(base))>TOLERANCE)// If it is not the transport itself
{
#endif

drop-unit unit_to_auto_unload;
--units_inside;
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_auto_unload);
CALC_WEIGHT;
cargo_hold=cargo_hold - w;
#endif
#if !INSTA_UNLOAD
sleep 1;
#endif
move unload_arm to z-axis 0 now;
move unload_arm to y-axis 0 now;
wait-for-move unload_arm along z-axis;
same=FALSE;
if(get XZ_HYPOT(get PIECE_XZ(unload_shoulder) - get UNIT_XZ(unit_to_auto_unload))<=TOLERANCE)//If it failed dropping
{
same=TRUE;
++units_inside;
#if LIMITED_CARGO_HOLD
h=get UNIT_HEIGHT(unit_to_auto_unload);
CALC_WEIGHT;
cargo_hold=cargo_hold + w;
#endif
attach-unit unit_to_auto_unload to 0 - 1;
}
#if EXPLODE_WHEN_UNLOADING
if(!same)
{
explode goal_arm type BITMAPONLY | BITMAP2;
}
#endif
#if FLAME_WHEN_UNLOADING
if(!same)
{
emit-sfx SFXTYPE_VTOL from goal_arm;
}
#endif
if(shape==0)
{
++pos_on_circle;
if(pos_on_circle>=max_pos)
{
pos_on_circle=0;
++num_circle;
}
}
if(shape==1)
{
++pos_on_row;
if(pos_on_row>=4*num_row+1)
{
pos_on_row=0;
++num_row;
}
}
if(shape==2)
{
++pos_on_row;
if(pos_on_row>=AUTO_UNLOAD_UNITS_PER_ROW)
{
pos_on_row=0;
++num_row;
}
}
if(shape==3)
{
++pos_on_row;
if(pos_on_row>max_pos)
{
pos_on_row=0;
++num_row;
}
}//end last shape choice
}//end not the transport itself// Can't happen when ID are stored, but anyway
#if QUIT_AUTO_UNLOAD_WHEN_MOVING
if(is_moving)// It is important to note that the TransportDrop() is called as soon as the transport starts decelerating, sometimes long before it's fully stopped. And that StopMoving that set is_moving to FALSE is only called when it's fully stopped. So there's some wait till full stop up there.
{
CLOSING_DOOR_ANIMATION
set BUSY to 0;
return;
}
#endif
}//end while(units_inside>0)
CLOSING_DOOR_ANIMATION
set BUSY to 0;
return;
#endif
}



#define REFRESH_MOVEMENT_ANIMATION 300
#define WHEEL_DIAMETER [6]

MovementAnimation()
{
#if DECLARE_ALL_LOCAL_VARS_AT_BEGINNING
#if LEAN_ON_SLOPE
var unitheading, last_pos, lxsnxs, lzsnzs;
#else
var unitheading, last_pos;
#endif
#else
var unitheading, last_pos;
#if LEAN_ON_SLOPE
var lxsnxs, lzsnzs;
#endif
#endif
unitheading=get XZ_ATAN(7);
last_pos=get PIECE_XZ(base);
while (TRUE)
{

// Creates waves if not transported and if moving
if (terrain_code != 0)
{
if(is_moving)
{
emit-sfx SFXTYPE_WAKE1 from wake1;
emit-sfx SFXTYPE_WAKE1 from wake2;
emit-sfx SFXTYPE_WAKE1 from wake3;
emit-sfx SFXTYPE_WAKE1 from wake4;
emit-sfx SFXTYPE_WAKE1 from wake5;
emit-sfx SFXTYPE_WAKE1 from wake6;
emit-sfx SFXTYPE_WAKE1 from wake7;
emit-sfx SFXTYPE_WAKE1 from wake8;
}
}

sleep REFRESH_MOVEMENT_ANIMATION;

#if LEAN_ON_SLOPE
// x_slope== slope of rotation around x == slope along axis z == "pitch"
// z_slope== slope of rotation around z == slope along axis x == "bank"
lxsnxs=x_slope;// old slope
lzsnzs=z_slope;// old slope
if(terrain_code!=0)// Not transported: read the ground slope
{
x_slope=get ATAN(get GROUND_HEIGHT(get PIECE_XZ(rear)) - get GROUND_HEIGHT(get PIECE_XZ(front)), get XZ_HYPOT(get PIECE_XZ(rear) - get PIECE_XZ(front)));
while(x_slope>32768)
{x_slope=x_slope - 65536;}
z_slope=get ATAN(get GROUND_HEIGHT(get PIECE_XZ(right)) - get GROUND_HEIGHT(get PIECE_XZ(left)), get XZ_HYPOT(get PIECE_XZ(right) - get PIECE_XZ(left)));
while(z_slope>32768)
{z_slope=z_slope - 65536;}
}
if(terrain_code==0 || terrain_code==2)// Transported or over water: inhibit slope leaning
{
x_slope=0;
z_slope=0;
}
lxsnxs=lxsnxs - x_slope;// slope delta with time
lzsnzs=lzsnzs - z_slope;// slope delta with time
if(lxsnxs<0)
{lxsnxs=0 - lxsnxs;}// absoluted
if(lzsnzs<0)
{lzsnzs=0 - lzsnzs;}// absoluted
turn hull to x-axis x_slope speed lxsnxs*1000/REFRESH_MOVEMENT_ANIMATION;
turn hull to z-axis z_slope speed lzsnzs*1000/REFRESH_MOVEMENT_ANIMATION;
#endif


// Note: I assume people will use LEAN_ON_SLOPE when and only when the unit is upright=1;
if((terrain_code==4) || ((terrain_code==1) && LEAN_ON_SLOPE))// If ((on dry ground) or (on shore if upright=1))
{

// Steer the wheels:
unitheading=unitheading - get XZ_ATAN(7);//now it's unit heading diff
turn wheel1 to y-axis 3*unitheading speed <40>;
turn wheel2 to y-axis 3*unitheading speed <40>;
turn wheel3 to y-axis 1*unitheading speed <40>;
turn wheel4 to y-axis 1*unitheading speed <40>;
turn wheel5 to y-axis 0-1*unitheading speed <40>;
turn wheel6 to y-axis 0-1*unitheading speed <40>;
turn wheel7 to y-axis 0-3*unitheading speed <40>;
turn wheel8 to y-axis 0-3*unitheading speed <40>;
unitheading=get XZ_ATAN(7);//Now it's actually the unit heading (or the opposite, and maybe shifted 180°)

// Spin the wheels proportionnaly to the speed:
last_pos=get XZ_HYPOT(last_pos - get PIECE_XZ(base));//Now it's the distance between last pos and current pos
last_pos=((((((last_pos*100)/WHEEL_DIAMETER)*65536)/314)*1000)/REFRESH_MOVEMENT_ANIMATION);//Now it's the wheel speed
spin wheel1 around x-axis speed last_pos;
spin wheel2 around x-axis speed last_pos;
spin wheel3 around x-axis speed last_pos;
spin wheel4 around x-axis speed last_pos;
spin wheel5 around x-axis speed last_pos;
spin wheel6 around x-axis speed last_pos;
spin wheel7 around x-axis speed last_pos;
spin wheel8 around x-axis speed last_pos;
last_pos=get PIECE_XZ(base);//Now it's the current pos, so the last post of next iteration

// Reset the wheels from buoy positions after going out of water:
turn wheel1 to z-axis <0> speed <70>;
turn wheel2 to z-axis <0> speed <70>;
turn wheel3 to z-axis <0> speed <70>;
turn wheel4 to z-axis <0> speed <70>;
turn wheel5 to z-axis <0> speed <70>;
turn wheel6 to z-axis <0> speed <70>;
turn wheel7 to z-axis <0> speed <70>;
turn wheel8 to z-axis <0> speed <70>;
}

if((terrain_code==2) || ((terrain_code==1) && !(LEAN_ON_SLOPE)))// If ((upright=1 and in sea) or (not upright=1 and in sea))
{
// Stop spining the wheels:
stop-spin wheel1 around x-axis;
stop-spin wheel2 around x-axis;
stop-spin wheel3 around x-axis;
stop-spin wheel4 around x-axis;
stop-spin wheel5 around x-axis;
stop-spin wheel6 around x-axis;
stop-spin wheel7 around x-axis;
stop-spin wheel8 around x-axis;

// Reset the wheel rotation, needed because of the order the engine apply rotations
turn wheel1 to x-axis <0> now;
turn wheel2 to x-axis <0> now;
turn wheel3 to x-axis <0> now;
turn wheel4 to x-axis <0> now;
turn wheel5 to x-axis <0> now;
turn wheel6 to x-axis <0> now;
turn wheel7 to x-axis <0> now;
turn wheel8 to x-axis <0> now;

// Reset the steering to 0:
turn wheel1 to y-axis <0> speed <40>;
turn wheel2 to y-axis <0> speed <40>;
turn wheel3 to y-axis <0> speed <40>;
turn wheel4 to y-axis <0> speed <40>;
turn wheel5 to y-axis <0> speed <40>;
turn wheel6 to y-axis <0> speed <40>;
turn wheel7 to y-axis <0> speed <40>;
turn wheel8 to y-axis <0> speed <40>;

// Turn the wheels to buoy position:
turn wheel1 to z-axis <-90> speed <70>;
turn wheel2 to z-axis <90> speed <70>;
turn wheel3 to z-axis <-90> speed <70>;
turn wheel4 to z-axis <90> speed <70>;
turn wheel5 to z-axis <-90> speed <70>;
turn wheel6 to z-axis <90> speed <70>;
turn wheel7 to z-axis <-90> speed <70>;
turn wheel8 to z-axis <90> speed <70>;
}
}
}


StartMoving()
{
signal SIG_MOVE;
set-signal-mask SIG_MOVE;
is_moving=TRUE;
/*spin wheel1 around x-axis speed <20> accelerate <5>;
spin wheel2 around x-axis speed <20> accelerate <5>;
spin wheel3 around x-axis speed <20> accelerate <5>;
spin wheel4 around x-axis speed <20> accelerate <5>;
spin wheel5 around x-axis speed <20> accelerate <5>;
spin wheel6 around x-axis speed <20> accelerate <5>;
spin wheel7 around x-axis speed <20> accelerate <5>;
spin wheel8 around x-axis speed <20> accelerate <5>;*/
}


StopMoving()
{
signal SIG_MOVE;
is_moving=FALSE;
/*stop-spin wheel1 around x-axis decelerate <20>;
stop-spin wheel2 around x-axis decelerate <20>;
stop-spin wheel3 around x-axis decelerate <20>;
stop-spin wheel4 around x-axis decelerate <20>;
stop-spin wheel5 around x-axis decelerate <20>;
stop-spin wheel6 around x-axis decelerate <20>;
stop-spin wheel7 around x-axis decelerate <20>;
stop-spin wheel8 around x-axis decelerate <20>;*/
}


setSFXoccupy(setSFXoccupy_argument)
{
terrain_code = setSFXoccupy_argument;
// 0 -> Transported: Unit is being loaded
// 1 -> Sea: Unit does not have upright=1 and is going into sea. Or unit has upright=1 and is going into shore. (From unloading, or ground, or deep sea for upright unit)
// 2 -> Sea: Unit has upright=1 and goes into deep sea. (From shore, or unloading)
// 3 -> ????
// 4 -> Land: Unit is being created, goes from sea (or shore if upright=1) to dry ground, or is unloaded

// I dunno if shore stand for shallow water or low level ground.
}


SmokeUnit(healthpercent, sleeptime, smoketype)
{
while( get BUILD_PERCENT_LEFT )
{
sleep 400;
}
while( TRUE )
{
healthpercent = get HEALTH;
if( healthpercent < 66 )
{
smoketype = SFXTYPE_BLACKSMOKE;
if( Rand( 1, 66 ) < healthpercent )
{
smoketype = SFXTYPE_WHITESMOKE;
}
emit-sfx smoketype from hull;
}
sleeptime = healthpercent * 50;
if( sleeptime < 200 )
{
sleeptime = 200;
}
sleep sleeptime;
}
}


Create()
{
#if DECLARE_ALL_LOCAL_VARS_AT_BEGINNING
#if LOAD_ONLY_PLAYER_UNITS
var uid;
#endif
#endif
INIT_LOADED_ID(65537) // Not necessary, but would prevent crashes in case we retrieve an ID not stored yet
units_inside=0;
is_moving=FALSE;
terrain_code=4;
DelayBeforeRestore=3000;
togglebarrel=rand(0,1);
#if LOAD_ONLY_PLAYER_UNITS
units_per_player=1073741819;
self_id=0 - 1;
#endif
#if LEAN_ON_SLOPE
x_slope=0;
z_slope=0;
#endif
#if LIMITED_CARGO_HOLD
cargo_hold=0;
#endif
hide leftflare;
hide rightflare;
set ACTIVATION to TRUE;
#if LOAD_ONLY_PLAYER_UNITS
sleep 70;
#if !DECLARE_ALL_LOCAL_VARS_AT_BEGINNING
var uid;
#endif
for(uid=1950;uid>=50;uid=uid - 50;)
{
if (get UNIT_HEIGHT(uid+1)==2621439 || get UNIT_HEIGHT(uid+1)==2512790)
{
units_per_player=uid;
}
}
uid=1;
while(self_id<0)
{
if (get UNIT_XZ(uid)==get PIECE_XZ(base))
{
if (get UNIT_Y(uid)==get PIECE_Y(base))
{
self_ID=uid;
}
}
++uid;
}
//Note: it is very possible that the self_ID catch the ID value of the factory instead of the ID value of the unit. It doesn't really matter as it later used only to determine the player number.
#endif

while(get BUILD_PERCENT_LEFT)// Wait until the unit is fully built
{sleep 200;}
start-script SmokeUnit();
start-script MovementAnimation();
}


SetMaxReloadTime(ReloadTime)
{
DelayBeforeRestore = ReloadTime * 2;
}

RestoreAfterDelay()
{
sleep DelayBeforeRestore;
turn turret to y-axis <0> speed <90>;
turn leftbarrel to x-axis <0> speed <90>;
turn rightbarrel to x-axis <0> speed <90>;
}

AimFromPrimary(piecenum)
{
piecenum=turret;
}

AimPrimary(heading, pitch)
{
signal SIG_PRIMARY;
set-signal-mask SIG_PRIMARY;
while(units_inside<MIN_MANPOWER_FOR_PRIMARY)
{
sleep 800;
}
turn turret to y-axis heading speed <120>;
#if AIM_VERTICALLY
turn leftbarrel to x-axis 0 - pitch speed <120>;// The x_slope and z_slope aren't taken into account, so the aiming is not accurate when the unit is on a slope.
turn rightbarrel to x-axis 0 - pitch speed <120>;// The x_slope and z_slope aren't taken into account, so the aiming is not accurate when the unit is on a slope.
wait-for-turn leftbarrel around x-axis;
wait-for-turn rightbarrel around x-axis;
#endif
wait-for-turn turret around y-axis;
start-script RestoreAfterDelay();
return (1);
}

QueryPrimary(piecenum)
{
piecenum=turret;
if(!togglebarrel)
{
piecenum=leftflare;
}
if(togglebarrel)
{
piecenum=rightflare;
}
}

FirePrimary()
{
if(!togglebarrel)
{
show leftflare;
}
if(togglebarrel)
{
show rightflare;
}
sleep 150;
hide leftflare;
hide rightflare;
togglebarrel=(!togglebarrel);
}

SweetSpot(piecenum)
{
piecenum = hull;
}

Killed(severity,corpsetype)
{
// The \Features\Corpses\ArmDuck_dead.tdf goes like:
// First sea wreckages
// Then an indestructible smudge
// Then land wreckages
// So by adding 4 to the corpsetype we switch from sea wreckage to land wreckage
// That way, I can have land wreck different from sea wreck
// Which allow me to have the first wreck passable in sea and impassable on land

corpsetype=1;
explode wheel6 type FALL | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode wheel1 type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode wheel7 type FALL | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode base type FALL | SMOKE | FIRE | BITMAP1;
explode base type FALL | SMOKE | FIRE | BITMAP3;
explode base type FALL | SMOKE | FIRE | BITMAP2;
if(severity<33)//If terrain_code is 2, then, assuming the unit is upright, it means the unit is into the deep sea, and sea wreckages shouldn't be blocking, so we skip the first wreck which is blocking
{
corpsetype=corpsetype + 4*(terrain_code!=2 && terrain_code!=1);
return;
}
corpsetype=2;
explode hull type SHATTER | BITMAP5;
explode wheel2 type FALL | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode wheel8 type FALL | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode wheel3 type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP4;
if(severity<66)
{
corpsetype=corpsetype + 4*(terrain_code!=2 && terrain_code!=1);
return;
}
corpsetype=3;
explode turret type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP1;
explode wheel4 type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode wheel5 type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP4;
explode leftdoor type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP2;
explode rightdoor type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP2;
if(severity<99)
{
corpsetype=corpsetype + 4*(terrain_code!=2 && terrain_code!=1);
return;
}
corpsetype=4;
explode base type FALL | SMOKE | FIRE | BITMAP2;
corpsetype=corpsetype + 4*(terrain_code!=2 && terrain_code!=1);
return;
// BITMAP1: descent-like explosion, same as 3
// BITMAP2: nice round explosion
// BITMAP3: descent-like explosion, same as 1
// BITMAP4: small explosion
// BITMAP5: mini laser explosion
// BITMAPNUKE: bertha shot explosion
}
Those last lines reminds me I haven't even mentionned the "use passable corpse when in water, unpassable corpse when on land" on the list of features the ArmDuck showcase. :P
User avatar
Snipawolf
Posts: 4357
Joined: 12 Dec 2005, 01:49

Post by Snipawolf »

That is one long script, my friend... I am glad you minitaurized it, or else it would remind me of reading zoombies stories..
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

The height in Spring is calculated as the radius of the hit sphere multiplied with 65536, for s3os you can just read the radius you set in the s3o.

I was thinking about making the pump extract faster if it's on a larger deposit but that would make more metal give quadratic gains (since it'd produce more per emptying and empty more often). I guess I could give it such a small extraction rate that it's always zero and have it make metal instead...
nemovc
Posts: 5
Joined: 21 Feb 2007, 11:17

Post by nemovc »

some people here just seem to be too good at scripting. anyway, where can I find a good tutorial on scripting for spring? the other sections all have heaps of tutorials, but I can't find a single good one on how to script units.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

The TA Design Guide explains the basics, after that you should read the changelog to see what Spring added and study loads of different scripts.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7049
Joined: 16 Nov 2004, 13:08

Post by zwzsg »

KDR_11k wrote:for (uid=5000;uid >= 0;--uid) { //thanks, zwzsg
I wish you'd use for(uid=get MAX_ID;uid>=1;--uid) instead.


The "get MAX_ID" ensure the script will autoadapt to whatever unit limit. Usually get MAX_ID is 4999, but if you play with sixteen player 500 units each, I guess it's higher. And Spring may not stay capped at 500 unit per player forever....

And the ID zero isn't a regular unit ID, it's some sort of special case which has some properties recopied from the unit which is running the script, but not all, and anyway what I mean is the ID 0 should be left out of the loop. (Contrary to what I used to believe).

(And yes 1 to 4999 isn't divisible by the number of player, yet such is the range of unit ID.)

Argh wrote:Zszwg has made several cryptic posts referring to Spring handling aiming-interruption code poorly
What I said is that Spring retries aiming every half second of something like that, even if the last aiming was still in progress. While it can cause problems if you have long aiming animation that have to be left alone for some time to complete, I feel it's better than the "try once and jam forever if fail" aiming TA used. The first time I noticed that, maybe I was annoyed that it didn't work exactly like TA, but now that I'm aware it's easy to design aiming script protected against being called again before getting finished (anyway a player of TA compulsively clicking attack would achieve the same effect), and all in all I'd say Spring's way offer more advantage, so I wouldn't call it "poor".



While I'm at it: There are no floats in scripts. Only integers. Signed 32 bits integers to be precise. Everything that isn't integer, such a 5/3 or 0.5 gets floored to nearest lower integer.

That means that If(Experience < 0.500000) compile into the same as If(Experience < 0) which I believe is not what you want. IRC "get VETERAN_LEVEL" return the experience * 100.

Sometimes you see decimal numbers between [ ] or < >. That is because [ ] is a preprocessing command that means "multiply what's inside by 163840", and < > is a preprocessing command that means "multiply what's inside by 182". You know what's a preprocessor, right?
So when you write
move foo to y-axis [0.5] now;
turn bar to y-axis <0.7> now;
in reality it is the same as:
move foo to y-axis 81920 now;
move foo to y-axis 127 now;
It's just because some people felt it was more convenient to work with units that are humanly apprehendable. [1] correspond to 2.5 pixels (in TA), it's a unit we can feel and work with intuitivly. <1> correspond to 1 degree, everybody is used to degree.

But in the script at the end there's no decimal, no floating points, only integers.


Also, Arg, having a whole function constantly running to do nothing but copy "VETERAN_LEVEL" into a variable is pure wastage. I have not measured, but I'm certain the performance loss of having that constantly running function is incredibly more huge than doing a "get VETERAN_LEVEL" every time it aims. Actually I wouldn't be suprised if reading a "get" is faster than reading a script static-var. Not to mention the code complication, the added bytes to COB length, the slow reactivness to veterancy change,..... Also you forgot the parameter passed to AimPrimary, the signal bit, the aiming animation,... If it's understated that it's up to whoever reuse that script to add them, then you could at least write so in a comment.

Hide the gun, and turn it to an angle where it is NEVER going to satisfy Tolerance!
Unless I'm very mistaken, the Spring engine doesn't care how you turn your gun. The tolerance is measured relatively to the unit heading. Not relatively to the cannon.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

I think that part about tolerance is true, after all how would spring know which rotations should have the tolerance and which ones not? Of course Spring being spring I could imagine there's some really hacky code to determine that...
Post Reply

Return to “Game Development”