Unit crashing spring

Unit crashing spring

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

Post Reply
User avatar
Guessmyname
Posts: 3301
Joined: 28 Apr 2005, 21:07

Unit crashing spring

Post by Guessmyname »

NOTE: This is for use in the latest dev version of Spring! (r3467 at time of writing)

Considering how complex the unit script is, this is probably what's causing Spring to crash when the unit is created

So this is the script. It contains a lot of comments to help people:

Code: Select all

// Thank's be to 'Argh' for his script repository. 
#include "STANDARD_COMMANDS_GPL.h"
#include "FC_SFX.h"

//defines pieces in the unit's s3o or 3do model file
piece base, hullp1, hullp2, hullp3, eng;
piece sfx1, sfx2, sfx3;
piece turret, barrel, fp;
piece explo_base, explo_y, explo_point;

static-var restore_delay, healthlevel;
static-var d3, d6, d12;
static-var armour, heat;
static-var hitby;
static-var hitanglex, hitangley;
static-var wepstr; //weapon strength
static-var PR; //penetration roll
static-var defspeed;

#define	SIG_AIM1	2
#define	SIG_MOVE	4

//Scripted Effects
//WARNING! sfx types 1-3 are already used by FC_SFX.h!
#define NOVAFX 1027 //sfx type 4

//scripted weapons
//WARNING! weapons 13-16 are already used by FC_SFX.h!
#define NOVACANNON 2049 //weapon2 - will actually fire this, rather than detonate it

VarReduce()	//this is a custom function put in before Create() because Scriptor compiles things downwards.
			//As Create calls this function, it needs to exist before Create() or compile errors will occur
			//this applies to all functions you want to call anywhere - they need to be included before the caller
{
	if(heat > 0)
		{
		heat = heat - 1;
		}
	sleep 1000; //once per second
}

ConstantFX() //used for engine effects
{
	emit-sfx ENGFX from sfx1;
	emit-sfx ENGFX from sfx2;
	emit-sfx ENGFX from sfx3;
	sleep 100; //the above effects all occur every 10th of a second
}

DamageFX() //damage effects, obviously
{
	while( get BUILD_PERCENT_LEFT )	//this stops the unit spurting fire and smoke whilst being built
	{								//BUILD_PERCENT_LEFT gives a percentage of how much unit there is left to build
		sleep 1000;					//When it reaches 0, the unit is complete, and the while function ends
	}								//While functions run until the variable in brackets is 0, hence why this works
	get HEALTH; //gets the unit's health - is returned as a percentage	
	healthlevel = HEALTH;
	if(healthlevel < 50) //below 50% health
		{
		emit-sfx SMOKEFX from explo_point;
		}
	if(healthlevel < 25) //below 25% health
		{
		emit-sfx FIREFX from explo_point;
		}
	sleep 1000;
}

Create() //run when the unit is created (as in: when building begins)
{
	spin explo_base around x-axis speed <300>;
	spin explo_y around y-axis speed <300>;
	start-script VarReduce();
	start-script ConstantFX();
	start-script DamageFX();
	set MAX_SPEED to 5;
	defspeed=5;
	restore_delay = 2000;
	armour=10;
	heat=0;
	wepstr=0;
	PR=0;
}

CrewStunned()
{
	set MAX_SPEED to 0;
	sleep 5000; //five seconds
	set MAX_SPEED to defspeed; //default speed
}

CrewShaken()
{
	set MAX_SPEED to 1;
	sleep 5000; //five seconds
	set MAX_SPEED to defspeed; //default speed
}

PenetratingHit()
{
	emit-sfx FIREFX from explo_point; //visual clue to show weapon penetration
	d6 = RAND(1,6);
	if(heat>50)
	{
		d6 = d6 + 1;
	}
	if(heat>100)
	{
		d6 = d6 + 2;
	}
	if(d6==1)
	{
		call-script CrewStunned();
	}
	if(d6==2)
	{
		call-script CrewShaken();
	}
	if(d6==3)
	{		
		emit-sfx SMALLEXPLO from explo_point;
	}
	if(d6==4)
	{		
		set MAX_SPEED to 0;
		defspeed=0;
	}
	if(d6==5)
	{
		armour = armour - 1;
	}
	if(d6==6)
	{		
		emit-sfx MEDEXPLO from explo_point;
	}
	if(d6==7)
	{
		armour = armour - 2;
	}
	if(d6==8)
	{		
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		//will destroy the unit entirely
	}	
}

HitResults()
{
	d6 = RAND(1,6);
	if(heat>50)
	{
		d6 = d6 + 1;
	}
	if(heat>100)
	{
		d6 = d6 + 2;
	}
	PR = wepstr + d6;
	if(PR > armour)
	{
		call-script PenetratingHit();
	}
}

/*hitby tags
Curse the fact that Scriptor won't support strings!
	0 = Plasma weapon
	1 = Laser weapon
	2 = Missile weapon
	3 = Torpedo
	4 = Slug
	5 = Nova cannon
	6 = Mines
	7 = Cutting Beam
	8 = (standin for another 'Special' weapon I haven't thought up yet)
*/

/*index of Weapon IDs

0 = plasma cannon
001 = light plasma gun
002 = Anti-Ship Cannon

100 = Anti-FigB Laser
101 = Anti-Ship Laser
102 = Heavy Anti-Ship Laser

200 = Seeker Missile
201 = Heavy Missile
202 = Dumb Rocket
203 = Tac-Nuke

300 = Torpedo
301 = Swarm Torpedo
302 = Shotgun Torpedo

400 = SCannon
401 = RailCannon

500 = Nova Cannon

600 = Mine
601 = Anti-Matter mine (nasty bastards)

700 = Cutting beam
*/

HitByWeapID(x, y, id, damage) //run when the unit is hit. ID gives the ID of the weapon - most useful!
{
	hitanglex=x;
	hitangley=y;
	
	if(id==0) //plasma cannon
	{
		hitby=0;
		armour = armour - 0.1;
	}
	
	if(id==001) //light plasma
	{
		hitby=0;
	}
	
	if(id==002) //Anti-Ship (plasma) Cannon
	{
		hitby=0;
		armour = armour - 1;
	}
	
	if(id==100) //AFL
	{
		hitby=1;
		heat = heat + 1;
	}
	
	if(id==101) //ASL
	{
		hitby=1;
		heat = heat + 10;
	}
	
	if(id==200) //seeker missile
	{
		hitby=2;
		wepstr=6;
		call-script HitResults();
	}
	
	if(id==201 || id==202) //heavy missile and dumb missile
	{
		hitby=2;
		wepstr=7;
		call-script HitResults();
	}
	
	if(id==300) //torpedo
	{
		hitby=3;
		wepstr=9;
		call-script HitResults();
	}
	
	if(id==301) //swarm torpedo
	{
		hitby=3;
		wepstr=5;
		call-script HitResults();
	}
	
	if(id==302) //shotgun torpedo
	{
		hitby=3;
		wepstr=6;
		call-script HitResults();
	}
	
	if(id==400) //slug
	{
		hitby=4;
		wepstr=6;
		call-script HitResults();		
	}
	
	if(id==401) //rail cannon
	{
		hitby=4;
		wepstr=10;	
		call-script HitResults();	
	}
	
	if(id==500) //nova
	{
		hitby=5;
		armour = armour - 1;
		heat = heat + 50;
	}
	
	if(id==600) //mines
	{
		hitby=6;
	}
	
	if(id==700) //cutter beam
	{
		hitby=7;
		armour = armour - 0.01;
		heat = heat + 1;
	}
	return(100); //here, return tells the engine how much damage to do to the unit (as a percentage)
}

SetMaxReloadTime(time) //I can't remember what this does
	{
	restore_delay = time * 2;
	}

RestoreAfterDelay() //restores turrets to default positions
	{
	sleep restore_delay;
	turn turret to y-axis <0> speed <10>;
	turn barrel to x-axis <0> speed <10>;
	return 0;
	}

SweetSpot (piecenum) //where enemies shoot at - not used by Spring (Spring units will aim for the centre of the unit)
	{
	piecenum = base;
	}
	
QueryWeapon1 (piecenum) //the piece the weapon is fired from
	{
	piecenum = fp;
	}

AimFromWeapon1 (piecenum) //the point around which the weapon aims
	{
	piecenum = barrel;
	}

AimWeapon1(heading, pitch) //aiming anims for weapon1
	{
	signal SIG_AIM1;
	set-signal-mask SIG_AIM1;
	turn turret to y-axis heading speed <10>;
	turn barrel to x-axis (0 - pitch) speed <10>;
	return(TRUE);
	}

FireWeapon1() //called when the weapon fires
	{
	//here, you should be able to see that weapon1 is infact a dummy
	//as Nova weapons are supposed to charge up before firing,
	//I set it up so that weapon1 will tell scriptor when to fire...
	emit-sfx NOVAFX from fp; //charging effects
	heat = heat + 30;
	sleep 1000;	//The script will then wait a second of 'warm-up time'
	emit-sfx NOVACANNON from fp; //Fire the *real* Nova cannon
	return(0);
	}

/*hitby tags
Curse the fact that Scriptor won't support strings!
	0 = Plasma weapon
	1 = Laser weapon
	2 = Missile weapon
	3 = Torpedo
	4 = Slug
	5 = Nova cannon
	6 = Mines
	7 = Cutting Beam
	8 = (standin for another 'Special' weapon I haven't thought up yet)
*/

/*AimWeapon2(heading, pitch) //aiming anims for weapon2 (the real Nova Cannon that isn't meant to shoot on it's own)
	{
	sleep 99999999;
	}*/

Killed(severity, corpsetype) //Called when the unit dies
	{
	//Between here and return(0);, you can put a death anim. As I have here
	if(hitby==2 || hitby==3 || hitby==4 || hitby==6) //death caused by Slug, Torp, Mine or missile. || = OR
		{
		turn base to y-axis hitangley NOW;
		turn base to x-axis hitanglex NOW;
		move hullp1 to x-axis [10000] speed [1];
		spin hullp1 around z-axis speed <5>;
		sleep 1000;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 750;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 500;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 100;
		emit-sfx MEDEXPLO from explo_point;
		sleep 80;
		emit-sfx MEDEXPLO from explo_point;
		sleep 50;
		emit-sfx MEDEXPLO from explo_point;
		sleep 30;
		emit-sfx LARGEEXPLO from explo_point;
		}
	if(hitby==0 || hitby==1) //death caused by Laser or Plasma
		{
		spin hullp1 around z-axis speed <5>;
		sleep 1000;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 750;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 500;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 100;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 80;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 50;
		emit-sfx MEDEXPLO from explo_point;
		sleep 30;
		emit-sfx LARGEEXPLO from explo_point;
		}
	if(hitby==5 || hitby==7) //death caused by Nova or Cutting Beam
		{
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx MEDEXPLO from sfx1;
		emit-sfx MEDEXPLO from sfx2;
		emit-sfx MEDEXPLO from sfx3;
		}
	return(0);
	}
This is the unit's fbi file

Code: Select all

[UNITINFO]
{
	UnitName=CASD_attf_Nova;
	Name=Nova Attack Frigate;
	Buildpic=missingbp.jpg;
	
	//    Required Tags
	BuildCostEnergy=500;
	BuildCostMetal=0;
	BuildTime=1500;
	Category=CASD ATTF NOTSTRIKE;
	Description=Crew Size: 15. Nova Cannon;
	FootprintX=2;
	FootprintZ=2;
	MaxDamage=4000;
	MovementClass=Escort;
	ObjectName=CASD_attf_Nova;
	Side=CASD;
	SoundCategory=CASD_Ships;
	TEDClass=VTOL;
	
	//    Movement
	BrakeRate=0.01;
	Acceleration=0.01;
	CanMove=1;
	MaxVelocity=5;
	MaxSlope=10;
	TurnRate=900;
	
	//    Buildings
	
	//    Construction
	Builder=0;
	WorkerTime=0;
	
	//    Resources
	EnergyMake=100;
	EnergyStorage=0;
	EnergyUse=10;
	MetalStorage=-15;
	
	//    Abilities
	CanAttack=1;
	CanFly=1;
	CanGuard=1;
	CanPatrol=1;
	CanStop=1;
	
	//    Sight/Radar
	SightDistance=600;
	
	//    Misc
	CruiseAlt=70;
	ExplodeAs=LARGE_BOOM;
	dontland=1;
	MaxWaterDepth=0;
	NoChaseCategory=NOTSTRIKE;
	SelfDestructAs=LARGE_BOOM;
	SmoothAnim=0;
	AirStrafe=0;
	bmcode=1;
	noautofire=0;
	firestandorders=1;
	standingfireorder=2;
	mobilestandorders=1;
	standingmoveorder=1;
	idleAutoHeal=15;
	idleTime=1800;
	defaultmissiontype=VTOL_standby;
	steeringmode=1;
	scale=1;
	maneuverleashlength=1280;
	bankscale=1;
	seismicsignature=0;
	shownanoframe=0;

	//Weapons
	Weapon1=Novadummy;
		WeaponMainDir1=0 1 0; //xyz
		MaxAngleDif1=180;
	Weapon2=Novacannon;
	Weapon14=SMALL_BOOM;
	Weapon15=MED_BOOM;
	Weapon16=LARGE_BOOM;

[SFXTypes]
	{		
	explosiongenerator0=custom:whitetail; //Remember to thank Smoth
	explosiongenerator1=custom:FIRE_FX;
	explosiongenerator2=custom:SMOKE_FX;
	explosiongenerator3=custom:NOVAFX;
	}
}
The relevant weapon files

Code: Select all

[Novadummy]
	{
	ID=1000; //dummy / not-really-weapons weapons have id=1000
	name=dummy;
	rendertype=0;		/* 2D bitmap */
	lineofsight=1;
	turret=1;

	beamweapon=1;
	beamlaser=1;
	beamtime=0.01;
	thickness=2;
	corethickness=0.4;
	intensity=1; 
	laserflaresize=0;
	rgbcolor=0 0.5 1; //RGB
	rgbcolor2=1 1 1;

	range=500;
	reloadtime=0.01;
	//weapontimer=1;
	weaponvelocity=500;
	areaofeffect=15;
	soundstart=Meltagun;
	soundhit=Explosion5;
      	soundtrigger=1;
	//tolerance=6000;
	//pitchtolerance=3500; 
	energypershot=0;

	accuracy=0;

impulsefactor=0;
CollideFriendly=0;
AvoidFriendly=0;
NoSelfDamage=1;
craterMult=0;
craterBoost=0;

[DAMAGE]
	{
	default=0.000000001;
	}
}

[Novacannon]
	{
	ID=500; //IDs are organised by weapon strength
	name=Nova;
	rendertype=1;
	lineofsight=1;
	turret=1;
	model=plasmashot_ltblue.s3o;
	range=500;
	reloadtime=3;
	weapontimer=5;
	weaponvelocity=500;
	startvelocity=500;
	weaponacceleration=150;
	turnrate=0;
	areaofeffect=40;
	metalpershot=0;
	energypershot=60;
	soundstart=Plasmacannon;
	soundhit=Explosion5;
	firestarter=70;
	tolerance=8000;
	accuracy=500;
	explosiongenerator=custom:NOVA_BOOM;

impulsefactor=0;
impulseBoost=0;
CollideFriendly=0;
AvoidFriendly=0;
NoSelfDamage=1;
craterMult=0;
craterBoost=0;

[DAMAGE]
	{
	default=0.000000001;
	EscF=3000;
	AttF=3000;
	FigB=5000;
	}
}
Unit explosions

Code: Select all

[SMALL_BOOM]
	{
	ID=1000;
	name=vehicles;
	rendertype=4;
	ballistic=1;
	turret=1;

	range=0;
	reloadtime=3.6;
	weaponvelocity=250;
	areaofeffect=64;
	edgeeffectiveness=0.5;
	soundstart=largegun;
	soundhit=xplolrg4;

	explosiongenerator=custom:SMALL_BOOM;

	impulsefactor=0;
	[DAMAGE]
		{
		default=250;
		}
	}

[MED_BOOM]
	{
	ID=1000;
	name=vehicles;
	rendertype=4;
	ballistic=1;
	turret=1;

	range=0;
	reloadtime=3.6;
	weaponvelocity=250;
	areaofeffect=128;
	edgeeffectiveness=0.5;
	soundstart=largegun;
	soundhit=xplolrg4;

	explosiongenerator=custom:MED_BOOM;

	impulsefactor=0;
	[DAMAGE]
		{
		default=500;
		}
	}

[LARGE_BOOM]
	{
	ID=1000;
	name=vehicles;
	rendertype=4;
	ballistic=1;
	turret=1;

	range=0;
	reloadtime=3.6;
	weaponvelocity=250;
	areaofeffect=256;
	edgeeffectiveness=0.5;
	soundstart=largegun;
	soundhit=xplolrg4;

	explosiongenerator=custom:LARGE_BOOM;

	impulsefactor=0;
	[DAMAGE]
		{
		default=1000;
		}
	}
Me and Nemo's attempts to fix it:
[21:36:11] <[LEGIONS]Guessmyname> http://cs.selu.edu/~ssmith/BB/viewtopic.php?t=1178
[21:36:24] <[LEGIONS]Guessmyname> that's the script, unit fbi and weapon file
[21:37:10] <[LEGIONS]Guessmyname> the unit crashes Spring when created
[21:38:47] <[LEGIONS]Guessmyname> it's a bit complex
[21:39:34] <[S44]Nemo> #define NOVACANNON 2049 //weapon2 should be 2050
[21:39:43] <[S44]Nemo> if it starts a 2048
[21:39:51] <[S44]Nemo> starts at*
[21:40:37] <[LEGIONS]Guessmyname> ta!
[21:40:55] <[LEGIONS]Guessmyname> are the comments useful?
[21:41:29] <[LEGIONS]Guessmyname> wait - why would it be 2050 rather than 2049?
[21:41:41] <[LEGIONS]Guessmyname> weapon 1 would be 2048, wouldn't it?
[21:41:45] <[S44]Nemo> because you don't have a weapon0
[21:41:48] <[S44]Nemo> it doesn't happen
[21:41:54] <[LEGIONS]Guessmyname> oh
[21:42:08] <[LEGIONS]Guessmyname> that happen with sfx types too?
[21:42:10] <[S44]Nemo> I could be wrong, but I seem to remember it working like that when I played with emit-sfx last
[21:42:55] <[LEGIONS]Guessmyname> I'll have to twiddle that include as well...
[21:43:15] <[S44]Nemo> man, this mod is going to be impossible for non-epic players, isn't it :P
[21:43:28] <[LEGIONS]Guessmyname> this isn't Epic :P
[21:43:56] <[S44]Nemo> even worse then, since you won't have people who have an idea of what should be happening
[21:44:07] <[LEGIONS]Guessmyname> It'll be explained
[21:44:22] <[LEGIONS]Guessmyname> I have a readme already written
[21:44:30] <[LEGIONS]Guessmyname> but we have a more important issue
[21:44:33] <[LEGIONS]Guessmyname> ie the crashing
[21:44:42] <[LEGIONS]Guessmyname> the emit-sfx changes didn't do anything
[21:45:04] <[LEGIONS]Guessmyname> besides
[21:45:17] <[LEGIONS]Guessmyname> You could say the same about Gundam and S44
[21:46:41] <[S44]Nemo> hence their lack of players
[21:47:00] <[LEGIONS]Guessmyname> not really
[21:47:04] <[LEGIONS]Guessmyname> they're not BA
[21:47:12] <[LEGIONS]Guessmyname> that's the root of the lack of player
[21:47:13] <[LEGIONS]Guessmyname> s
[21:47:52] <[S44]Nemo> at least S44 and gundam have a group that should have a sense of what things can and can't do
[21:48:07] <[S44]Nemo> and in 44..most of it makes sense. units get shot at, they dive to the ground.
[21:48:27] <[S44]Nemo> we'll have to see how this project plays, I guess :P
[21:48:31] <[LEGIONS]Guessmyname> yeah
[21:48:39] <[LEGIONS]Guessmyname> If we can get past the crashing
[21:49:25] <[LEGIONS]Guessmyname> It shouldn't be too hard to work out what's happening, and if you don't read the readme, you deserve to get raped ingame
[21:49:57] <[LEGIONS]Guessmyname> (the readme applies to all mods)
[21:50:06] <[LEGIONS]Guessmyname> *readme thing
[21:50:30] <[LEGIONS]Guessmyname> Well, I'm off to bed
[21:50:34] <[LEGIONS]Guessmyname> gnight all
[21:50:37] <[S44]Nemo> wait!
[21:50:40] <[LEGIONS]Guessmyname> *g'night
[21:50:43] * [LEGIONS]Guessmyname waits
[21:50:48] <[S44]Nemo> post your explosions
[21:50:59] <[LEGIONS]Guessmyname> the scripts or the weapon files?
[21:51:02] <[LEGIONS]Guessmyname> Or both?
[21:51:06] <[S44]Nemo> but it crashes, instead of not just loading..er, nevermind
[21:51:15] <[LEGIONS]Guessmyname> ...
[21:51:25] <[S44]Nemo> oh
[21:51:28] <[S44]Nemo> commander=1?
[21:51:38] <[LEGIONS]Guessmyname> that was me trying to fix things
[21:51:42] <[S44]Nemo> its a commander, right?
[21:51:46] <[LEGIONS]Guessmyname> no
[21:51:48] <[S44]Nemo> oh
[21:51:56] <[S44]Nemo> is there a commander for that side?
[21:52:02] <[S44]Nemo> does that commander have commander=1?
[21:52:04] <[LEGIONS]Guessmyname> not yet
[21:52:13] <[S44]Nemo> there's your problem...?
[21:52:34] <[LEGIONS]Guessmyname> Sidedata is set to spawn the Nova Frigate as the starting unit
[21:52:50] <[LEGIONS]Guessmyname> the Nova Frigate is the unit that is crashing
[21:53:03] <[LEGIONS]Guessmyname> it's the only unit that is actually at an ingame stage
[21:53:06] <[S44]Nemo> yes, then it needs commander=1
[21:53:19] <[LEGIONS]Guessmyname> oh
[21:53:26] <[S44]Nemo> or else it'll just explode on spawning
[21:53:30] <[LEGIONS]Guessmyname> I thought I'd added that tag earlier...
[21:53:56] <[LEGIONS]Guessmyname> also
[21:54:02] <[LEGIONS]Guessmyname> still crashes :(
[21:54:15] <[LEGIONS]Guessmyname> oh, oops
[21:54:15] <[S44]Nemo> hrmph.
[21:54:19] <[LEGIONS]Guessmyname> missed commander
[21:54:22] <[S44]Nemo> <_<
[21:54:23] <[LEGIONS]Guessmyname> *misspelled
[21:54:34] <[S44]Nemo> http://phish.no-ip.info/LUA.zip there's the LUA stuff, btw
[21:54:46] <[LEGIONS]Guessmyname> thanks
[21:54:49] <[S44]Nemo> if you don't have any widgets, you can just unzip that in your spring directory
[21:55:01] <[S44]Nemo> if you have widgets, rename your LuaUI folder to anything else
[21:55:03] <[S44]Nemo> then unzip that
[21:55:13] <[LEGIONS]Guessmyname> 1: I have the widgets that come with spring
[21:55:13] <[S44]Nemo> then paste your old LuaUI folder into LuaUI-version number
[21:55:23] <[S44]Nemo> that's all? then you're fine
[21:55:42] <[LEGIONS]Guessmyname> 2: I'm using a seperate, clean spring installation + latest dev exe
[21:55:51] <[S44]Nemo> alrighty
[21:56:17] <[S44]Nemo> oh, also..if you're testing by starting spring.exe
[21:56:27] <[S44]Nemo> you need a team0 and team1 in sidedata
[21:56:34] <[S44]Nemo> just make the nova commander of both
[21:56:44] <[LEGIONS]Guessmyname> I have
[21:56:47] <[S44]Nemo> okay
[21:56:50] <[LEGIONS]Guessmyname> I know about that one :P
[21:59:03] <[LEGIONS]Guessmyname> hmm
[21:59:07] <[LEGIONS]Guessmyname> still crashin'
[21:59:20] <[S44]Nemo> odd.
[21:59:25] <[LEGIONS]Guessmyname> I'll post up the explosions etc anyway
[21:59:38] <[S44]Nemo> tried commenting out all the potentially crashy stuff in the script?
[21:59:45] <[S44]Nemo> various bits of Create()
[21:59:51] <[LEGIONS]Guessmyname> such as?
[22:00:07] <[LEGIONS]Guessmyname> all the script calls?
[22:01:18] * lurker[] has left #aata (Quit: timeout)
[22:01:34] * lurker[] has joined #aata
[22:02:06] * []AF has left #aata (Quit)
[22:02:07] <[S44]Nemo> eh, none of those look crashy
[22:02:22] <[LEGIONS]Guessmyname> well, I just tried it with those commented out
[22:02:28] <[LEGIONS]Guessmyname> still crashed
[22:02:34] <[S44]Nemo> right
[22:02:56] <[LEGIONS]Guessmyname> damnit, all my complicated scripts cause Spring to crash inexplicably...
[22:03:14] <[S44]Nemo> its not the script
[22:03:45] <[LEGIONS]Guessmyname> oh
[22:03:46] <[S44]Nemo> TEDCLASS=COMMANDER;
[22:03:51] <[S44]Nemo> tried it?
[22:04:28] <[LEGIONS]Guessmyname> will that stop it being an aircraft?
[22:04:33] <[LEGIONS]Guessmyname> it shouldn't...
[22:04:45] <[LEGIONS]Guessmyname> but knowing Spring...
[22:05:01] <[S44]Nemo> it wont
[22:05:05] <[S44]Nemo> the FF commanders have that
[22:05:12] <[LEGIONS]Guessmyname> and it still crashes :/
[22:05:38] <[LEGIONS]Guessmyname> this would be so much easier if Spring would actually say what was going wrong!
[22:05:50] <[S44]Nemo> add COMMANDER to category
[22:06:17] <[LEGIONS]Guessmyname> still crashes
[22:07:07] <[S44]Nemo> hm.
[22:07:21] <[S44]Nemo> does spring count down?
[22:07:24] <[S44]Nemo> 3-2-1 go?
[22:07:31] <[S44]Nemo> or do the 'press return to start'?
[22:07:56] <[LEGIONS]Guessmyname> press return
[22:08:06] <[LEGIONS]Guessmyname> I'm running it through Spring.exe
[22:08:11] <[LEGIONS]Guessmyname> I have to
[22:08:15] <[S44]Nemo> just makign sure it gets that far
[22:08:16] <[S44]Nemo> oh
[22:08:24] <[S44]Nemo> you don't have a start or stopmoving function
[22:08:31] <[LEGIONS]Guessmyname> should I?
[22:08:47] <[S44]Nemo> can't hurt. just return (0); or sleep 100 or something
[22:10:23] <[LEGIONS]Guessmyname> still crashes
[22:11:20] <[S44]Nemo> hm.
[22:11:37] <[S44]Nemo> missing any brackets anywhere? <_<
[22:12:04] <[S44]Nemo> there is a movementclass called Escort?
[22:12:43] <[LEGIONS]Guessmyname> yes to movement class
[22:12:47] <[LEGIONS]Guessmyname> no to the brackets
[22:14:33] <[S44]Nemo> hm. I don't see anything else missing right away..
[22:14:40] <[S44]Nemo> er, potentially missing
[22:15:02] <[LEGIONS]Guessmyname> its always something stupidly simple that causes these things
[22:15:13] <[S44]Nemo> yep >_>
[22:15:26] <[S44]Nemo> and its always impossible to find right away
[22:15:37] <[LEGIONS]Guessmyname> and as it's quarter past ten
[22:15:43] <[LEGIONS]Guessmyname> and I have school tomorrow
[22:15:45] <[LEGIONS]Guessmyname> goodnight
[22:15:48] <[LEGIONS]Guessmyname> and thanks
[22:15:54] <[S44]Nemo> alright, later
User avatar
yuritch
Spring 1944 Developer
Posts: 1018
Joined: 11 Oct 2005, 07:18

Post by yuritch »

I cannot see crash problems there (needs more looking into), but I see some small obvious problems.
First of all, scripts such as this:

Code: Select all

VarReduce()   //this is a custom function put in before Create() because Scriptor compiles things downwards. 
         //As Create calls this function, it needs to exist before Create() or compile errors will occur 
         //this applies to all functions you want to call anywhere - they need to be included before the caller
{ 
   if(heat > 0) 
      { 
      heat = heat - 1; 
      } 
   sleep 1000; //once per second 
}
will NOT run once per second, they will run ONCE PER GAME (as there is no looping condition in the script). You probably want this:

Code: Select all

VarReduce()
{
 while(TRUE) //loop the script indefinitely
 { 
   if(heat > 0) 
      { 
      heat = heat - 1; 
      } 
   sleep 1000; //once per second 
}
}
Take note of the while(TRUE) part - this is what makes the script loop, your code will run once and stop. The same error is in your other looping some-times-per-second scripts.
Second, your aim script doesn't wait for the weapon to finish aiming before allowing to fire. You have this:

Code: Select all

AimWeapon1(heading, pitch) //aiming anims for weapon1 
   { 
   signal SIG_AIM1; 
   set-signal-mask SIG_AIM1; 
   turn turret to y-axis heading speed <10>; 
   turn barrel to x-axis (0 - pitch) speed <10>; 
   return(TRUE); 
   }
You probably want this:

Code: Select all

AimWeapon1(heading, pitch) //aiming anims for weapon1 
   { 
   signal SIG_AIM1; 
   set-signal-mask SIG_AIM1; 
   turn turret to y-axis heading speed <10>; 
   turn barrel to x-axis (0 - pitch) speed <10>; 
   wait-for-turn turret around y-axis;
   wait-for-turn barrel around x-axis;
   return(TRUE); 
   }
This allows the shot to fire only after the weapon has finished aiming, yours will just fire the moment a target in found in range no matter how far away the weapon is facing (the weapon will start to aim, but the shot will be fired before the aiming completes).
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

Nemo's claim about the weapon sfxtype is wrong, weapons are counted from 1 and that equals 2048. I'm absolutely sure of this because, well, I scripted Dozerz and Kernel Panic and both make use of that.

You're decrementing the armor by 0.1, scriptor only supports integers so that gets rounded to 0.

Your damage die gets incremented by 3 when heat is >100 because both the heat>50 and heat>100 condition apply then.

You use get HEALTH as a statement. Get is a function, i.e. the value it gets is returned. You have to use variable = get HEALTH (I'm surprised Scriptor doesn't throw a compile error there). Also healthlevel=HEALTH will assign the constant's value (as defined in your exptype.h) instead of the health.

Set MAX_SPEED to 5 will practically immobilize the unit. Remember that a speed of 1.0 in the tdf equals a speed of 65536 in set MAX_SPEED.

You use variables as constants, that's slow and a waste of memory. When you have a value that doesn't get changed use #define to make it a constant.

You can also use local variables by using var in a function rather than definign a static-var. Static vars are only for values that need to persist even after the function ends and be identical between functions, don't use them for something like dice that are only relevant for one function.

Your more complex scripts always crash because you seem to lack understanding about BOS.

Also your comments are too verbose, you only need to explain what you're doing with that code, not what each command does because the reader is probably proficient in BOS already and will recognize it. Never mind that most if not all of these are named pretty self-explanatory (hm, what would get BUILD_PERCENT_LEFT return?).

BTW, does HitByID get called when the impact is not on the unit but it still receives splash damage? I know HitByWeapon only cares about direct hits.
User avatar
Nemo
Spring 1944 Developer
Posts: 1376
Joined: 30 Jan 2005, 19:44

Post by Nemo »

Ah. Whooops...

That's what happens when you're striving to find a problem. Sorry about that.

Edit: Yes, HitByWeaponId counts splash damage. I am absolutely sure about that, because its how my suppressing fire works.
User avatar
Guessmyname
Posts: 3301
Joined: 28 Apr 2005, 21:07

Post by Guessmyname »

Modified script:

Code: Select all

// Thank's be to 'Argh' for his script repository. 
#include "STANDARD_COMMANDS_GPL.h"
#include "FC_SFX.h"

piece base, hullp1, hullp2, hullp3, eng;
piece sfx1, sfx2, sfx3;
piece turret, barrel, fp;
piece explo_base, explo_y, explo_point;

static-var restore_delay, bMoving;
static-var armour, heat;
static-var hitby;
static-var hitanglex, hitangley;
static-var wepstr; //weapon strength
static-var defspeed;

#define	SIG_AIM1	2
#define	SIG_MOVE	4

//Scripted Effects
//WARNING! sfx types 1-3 are already used by FC_SFX.h!
#define NOVAFX 1027 //sfx type 4

//scripted weapons
//WARNING! weapons 13-16 are already used by FC_SFX.h!
#define NOVACANNON 2050 //weapon2 - will actually fire this, rather than detonate it

VarReduce()
{
	while(TRUE)
	{
	if(heat > 0)
		{
		heat = heat - 1;
		}
	sleep 1000; //once per second
	}
}

ConstantFX() //used for engine effects
{
	while(TRUE)
	{
	emit-sfx ENGFX from sfx1;
	emit-sfx ENGFX from sfx2;
	emit-sfx ENGFX from sfx3;
	sleep 100;
	}
}

DamageFX() //damage effects, obviously
{
	var healthlevel;
	while(TRUE)
	{
	while( get BUILD_PERCENT_LEFT )	//this stops the unit spurting fire and smoke whilst being built
	{
		sleep 1000;
	}
	healthlevel = get HEALTH; //gets the unit's health - is returned as a percentage	
	if(healthlevel < 50) //below 50% health
		{
		emit-sfx SMOKEFX from explo_point;
		}
	if(healthlevel < 25) //below 25% health
		{
		emit-sfx FIREFX from explo_point;
		}
	sleep 1000;
	}
}

Create()
{
	spin explo_base around x-axis speed <300>;
	spin explo_y around y-axis speed <300>;
	start-script VarReduce();
	start-script ConstantFX();
	start-script DamageFX();
	defspeed=(5 * 65536);
	restore_delay = 2000;
	armour=100;
	heat=0;
	wepstr=0;
	bMoving=FALSE;
}

StartMoving()
{
	bMoving=TRUE;
}

SopMoving()
{
	bMoving=FALSE;
}

CrewStunned()
{
	set MAX_SPEED to 0.00000001;
	sleep 5000; //five seconds
	set MAX_SPEED to defspeed; //default speed
}

CrewShaken()
{
	set MAX_SPEED to (65536); //65536 = 1.0 in the maxvelocity fbi tag
	sleep 5000; //five seconds
	set MAX_SPEED to defspeed; //default speed
}


PenetratingHit()
{
	var d6;
	emit-sfx FIREFX from explo_point; //visual clue to show weapon penetration
	d6 = RAND(1,6);
	if(heat>50)
	{
		d6 = d6 + 1;
	}
	if(heat>100)
	{
		d6 = d6 + 1;
	}
	if(d6==1)
	{
		call-script CrewStunned();
	}
	if(d6==2)
	{
		call-script CrewShaken();
	}
	if(d6==3)
	{		
		emit-sfx SMALLEXPLO from explo_point;
	}
	if(d6==4)
	{		
		set MAX_SPEED to 0.00001;
		defspeed=0;
	}
	if(d6==5)
	{
		armour = armour - 1;
	}
	if(d6==6)
	{		
		emit-sfx MEDEXPLO from explo_point;
	}
	if(d6==7)
	{
		armour = armour - 2;
	}
	if(d6==8)
	{		
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx LARGEEXPLO from explo_point;
		//will destroy the unit entirely
	}	
}

HitResults()
{
	var d6;
	var PR;
	d6 = RAND(1,6);
	if(heat>50)
	{
		d6 = d6 + 1;
	}
	if(heat>100)
	{
		d6 = d6 + 1;
	}
	PR = wepstr + d6;
	if(PR > armour)
	{
		call-script PenetratingHit();
	}
}

/*hitby tags
Curse the fact that Scriptor won't support strings!
	0 = Plasma weapon
	1 = Laser weapon
	2 = Missile weapon
	3 = Torpedo
	4 = Slug
	5 = Nova cannon
	6 = Mines
	7 = Cutting Beam
	8 = (standin for another 'Special' weapon I haven't thought up yet)
*/

/*index of Weapon IDs

0 = plasma cannon
001 = light plasma gun
002 = Anti-Ship Cannon

100 = Anti-FigB Laser
101 = Anti-Ship Laser
102 = Heavy Anti-Ship Laser

200 = Seeker Missile
201 = Heavy Missile
202 = Dumb Rocket
203 = Tac-Nuke

300 = Torpedo
301 = Swarm Torpedo
302 = Shotgun Torpedo

400 = SCannon
401 = RailCannon

500 = Nova Cannon

600 = Mine
601 = Anti-Matter mine (nasty bastards)

700 = Cutting beam
*/

HitByWeapID(x, y, id, damage)
{
	hitanglex=x;
	hitangley=y;
	
	if(id==0) //plasma cannon
	{
		hitby=0;
		armour = armour - 1;
	}
	
	if(id==001) //light plasma
	{
		hitby=0;
	}
	
	if(id==002) //Anti-Ship (plasma) Cannon
	{
		hitby=0;
		armour = armour - 5;
	}
	
	if(id==100) //AFL
	{
		hitby=1;
		heat = heat + 1;
	}
	
	if(id==101) //ASL
	{
		hitby=1;
		heat = heat + 10;
	}
	
	if(id==200) //seeker missile
	{
		hitby=2;
		wepstr=60;
		call-script HitResults();
	}
	
	if(id==201 || id==202) //heavy missile and dumb missile
	{
		hitby=2;
		wepstr=70;
		call-script HitResults();
	}
	
	if(id==300) //torpedo
	{
		hitby=3;
		wepstr=90;
		call-script HitResults();
	}
	
	if(id==301) //swarm torpedo
	{
		hitby=3;
		wepstr=50;
		call-script HitResults();
	}
	
	if(id==302) //shotgun torpedo
	{
		hitby=3;
		wepstr=60;
		call-script HitResults();
	}
	
	if(id==400) //slug
	{
		hitby=4;
		wepstr=60;
		call-script HitResults();		
	}
	
	if(id==401) //rail cannon
	{
		hitby=4;
		wepstr=100;	
		call-script HitResults();	
	}
	
	if(id==500) //nova
	{
		hitby=5;
		armour = armour - 1;
		heat = heat + 50;
	}
	
	if(id==600) //mines
	{
		hitby=6;
	}
	
	if(id==700) //cutter beam
	{
		hitby=7;
		armour = armour - 1;
		heat = heat + 1;
	}
	return(100); //here, return tells the engine how much damage to do to the unit (as a percentage)
}

SetMaxReloadTime(time)
	{
	restore_delay = time * 2;
	}

RestoreAfterDelay()
	{
	sleep restore_delay;
	turn turret to y-axis <0> speed <10>;
	turn barrel to x-axis <0> speed <10>;
	return 0;
	}

SweetSpot (piecenum) //where enemies shoot at - not used by Spring (Spring units will aim for the centre of the unit)
	{
	piecenum = base;
	}
	
QueryWeapon1 (piecenum)
	{
	piecenum = fp;
	}

AimFromWeapon1 (piecenum)
	{
	piecenum = barrel;
	}

AimWeapon1(heading, pitch)
	{
	signal SIG_AIM1;
	set-signal-mask SIG_AIM1;
	turn turret to y-axis heading speed <10>;
	turn barrel to x-axis (0 - pitch) speed <10>;	
	wait-for-turn turret around y-axis;
	wait-for-turn barrel around x-axis; 
	return(TRUE);
	}

FireWeapon1()
	{
	emit-sfx NOVAFX from fp; //charging effects
	heat = heat + 30;
	sleep 1000;	//The script will then wait a second of 'warm-up time'
	emit-sfx NOVACANNON from fp; //Fire the *real* Nova cannon
	return(0);
	}

/*AimWeapon2(heading, pitch)
	{
	sleep 99999999;
	}*/

Killed(severity, corpsetype)
	{
	if(hitby==2 || hitby==3 || hitby==4 || hitby==6) //death caused by Slug, Torp, Mine or missile. || = OR
		{
		turn base to y-axis hitangley NOW;
		turn base to x-axis hitanglex NOW;
		move hullp1 to x-axis [10000] speed [1];
		spin hullp1 around z-axis speed <5>;
		sleep 1000;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 750;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 500;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 100;
		emit-sfx MEDEXPLO from explo_point;
		sleep 80;
		emit-sfx MEDEXPLO from explo_point;
		sleep 50;
		emit-sfx MEDEXPLO from explo_point;
		sleep 30;
		emit-sfx LARGEEXPLO from explo_point;
		}
	if(hitby==0 || hitby==1) //death caused by Laser or Plasma
		{
		spin hullp1 around z-axis speed <5>;
		sleep 1000;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 750;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 500;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 100;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 80;
		emit-sfx SMALLEXPLO from explo_point;
		sleep 50;
		emit-sfx MEDEXPLO from explo_point;
		sleep 30;
		emit-sfx LARGEEXPLO from explo_point;
		}
	if(hitby==5 || hitby==7) //death caused by Nova or Cutting Beam
		{
		emit-sfx LARGEEXPLO from explo_point;
		emit-sfx MEDEXPLO from sfx1;
		emit-sfx MEDEXPLO from sfx2;
		emit-sfx MEDEXPLO from sfx3;
		}
	return(0);
	}
EDIT: This has stopped the crashing as well! Thankyou all!

EDIT: Huh. Spring crashes when you script-fire from a point object. What can you script-fire from?

EDIT: And dontland=1; does nothing at all, it seems
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

You can fire from point objects (or empties), the sfx-type number is wrong. It should be 2049, not 2050.
User avatar
Guessmyname
Posts: 3301
Joined: 28 Apr 2005, 21:07

Post by Guessmyname »

I'd just noticed that, sorry

They shoot straight up when fired from point objects :shock:
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

Ballistic weapons can't be force fired properly, they fly almost vertically. Dunno why, probably the aiming code interfering or something.

Hm, doesn't seem to be the problem. How is your empty object oriented? They face forward by default, you have to turn them to make them fire in any other direction.

And you misspelled "StopMoving".
User avatar
rattle
Damned Developer
Posts: 8278
Joined: 01 Jun 2006, 13:15

Post by rattle »

I'd make the AimWeapon function pause for a second and let the unit fire normally instead of using emit-sfx to fire weapons.

Ballistics seem to have their own will yeah. Normal LOS weapons (non beamlasers) etc work fine.
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

Rattle: That would cause the charge animation whether the unit fires or not. Unfortunately we have no "aiming complete, before firing" function. That would be pretty damn useful to handle charge animations or e.g. weapon malfunctions (e.g. firing into a wrong direction if a random chance happened) that would only happen when the weapon actually fires but must not create the normal projectile (yet). Completing the aim function does not guarantee that the unit attacks, it could have lost track of the target or received a stop order before finishing.

Also, beamlasers do work fine, you just have to have a beamtime of one frame.
Warlord Zsinj
Imperial Winter Developer
Posts: 3742
Joined: 24 Aug 2004, 08:59

Post by Warlord Zsinj »

What happened to the probe droid and imperial radar, eh? ;P
User avatar
rattle
Damned Developer
Posts: 8278
Joined: 01 Jun 2006, 13:15

Post by rattle »

KDR_11k wrote:Also, beamlasers do work fine, you just have to have a beamtime of one frame.
Which makes them useless IMO.

Hm... what if AimWeaponX starts another function for the visual charge up effect which also fires a round through sfx-emit at the end. FireWeaponX breaks the function before it can emit. Would need an additional static-var to let AimWeaponX know that a charge is in progress.

Code: Select all

#define SIG_CHARGE 24
static-var isCharging;

ChargeWeapon(duration)
{
	var i, delay;
	delay = 50;

	isCharging = TRUE;
	for (i = delay; i < duration; i = i + delay)
	{
		emit-sfx fart from butt;
		sleep delay;
	}
	start-script FireCharge(250);
}
FireCharge(delay)
{
	// This function is neccessary because you need a little delay for the weapon to fire and FireWeapon1() to get called.

	set-signal-mask SIG_CHARGE;
	sleep delay;
	emit-sfx kick from foot;
	isCharging = FALSE;
}

AimWeapon1(pitch, heading)
{
	signal SIG_AIM1;
	set-signal-mask SIG_AIM1;

	// Not allowed to reaim when charging
	if (isCharging == TRUE) return 1;

	turn turret to y-axis heading;
	turn barrel to x-axis 0-pitch;

	call-script ChargeWeapon(1000);

	wait-for-turn turret around y-axis;
	wait-for-turn turret around x-axis;

	return 0;
}
FireWeapon1()
{
	// The signal will prevent the weapon from being fired twice
	signal SIG_CHARGE;
	isCharging = FALSE;
}
An idea...
User avatar
Guessmyname
Posts: 3301
Joined: 28 Apr 2005, 21:07

Post by Guessmyname »

Warlord Zsinj wrote:What happened to the probe droid and imperial radar, eh? ;P
I'm remodelling the probe droid's arms that they can be UV-ed properly.

All my mod work is being hampered by the fact that, as it's getting close to GCSE exam time, my teachers are piling homework on us:

Usually, I have about 6 hours of free time. Take one from that for eating tea and general misc stuff. Then take another 2 because of homework, and finally remove another hour that I've devoted to this short story thingydo (I'll post it up in Offtopic when it's done) I have to write for my English coursework. That leaves 2 hours (more or less) of real free time. Even assuming I use it all on modding, I can't do that much in 2-ish hours

Fortunately, come July, I'll have all the free time in the world!
User avatar
KDR_11k
Game Developer
Posts: 8293
Joined: 25 Jun 2006, 08:44

Post by KDR_11k »

rattle wrote:
KDR_11k wrote:Also, beamlasers do work fine, you just have to have a beamtime of one frame.
Which makes them useless IMO.
You can just emit them again the next frame.

Your script is strange, it notices the target, starts moving its turret and simultaneously charge its gun, fork a thread that handles shooting, waits for the turret to finish aiming and then tells the weapon not to fire. When it receives another aiming call (spring gives those out roughly twice a second) it tells the weapon to fire immediately if it's charging, no questions asked. Also sleep 50 sleeps for two frames, you'd tell it to sleep for 20x2 frames, that's more than one second.
User avatar
Guessmyname
Posts: 3301
Joined: 28 Apr 2005, 21:07

Post by Guessmyname »

I've rewritten that.

The original idea was that the beamlaser would act as a 'target painter'. The actuall damage-dealing weapon would be a 'pulse' that travelled along the beamlaser. Unfortunately this didn't work too well, especially if the unit was moving at the time of firing
Warlord Zsinj
Imperial Winter Developer
Posts: 3742
Joined: 24 Aug 2004, 08:59

Post by Warlord Zsinj »

I was just teasing guessmyname; but I'm glad to see it's been done.
Post Reply

Return to “Game Development”