Vice City: Multiplayer

Server Development => Scripting and Server Management => Topic started by: Mötley on Aug 08, 2016, 06:51 PM

Title: Understanding better usages for spheres
Post by: Mötley on Aug 08, 2016, 06:51 PM
Okay So I had other methods of using spheres but I hate my methods. So I went into a big hunt in script releases in VCMP and LU, then I noticed Juppi's pay n spray release in LU "Awesome/amazing scriptwriter btw".

How in the heck did he determine what sphere is what, I am mind fu$#ed. I love it though,
So with that I want to take this as a learning opportunity.

The entire script is below \/.

Please I would really love to understand his method better as well in general, I would love the learning opportunity PLEASE :D

/*
Pay'n'Spray
--------------------------------------------------
This is a script which enables Pay'n'Sprays in LU.

Author: Juppi
*/

// Settings
SPHERE_COLOUR <- ::Colour( 25, 25, 255 );
const SPHERE_RADIUS = 3.0;
const GARAGE_RADIUS = 15.0; // Garage activation radius

enum VEHICLE_TYPE
{
NORMAL, // Normal vehicles which can be re-sprayed
EMERGENCY, // Emergency vehicles
NOTFORGARAGE, // Too big/not supported vehicles
};

// Storage
const MAX_GARAGES = 3;
g_Garages <- array( MAX_GARAGES, null );


function onScriptLoad()
{
print( "Liberty Unleashed Pay'n'Spray script loaded" );

// Install the Pay'n'Sprays
InitGarages();

// Set up a constant timer to process the garages
NewTimer( ProcessGarages, 750, 0 );

return 1;
}

/*
 * A storage class for garage information.
 * This includes static data like position etc. but also the status of the garage
 */
class CPayNSpray
{
// Construct a new garage
function constructor( id, pos, campos, camlookat )
{
ID = id;
Pos = pos;
CamPos = campos;
CamLookAt = camlookat;

::CreateBlip( ::BLIP_PNS, pos );

local sphere = ::CreateSphere( pos, SPHERE_RADIUS, ::SPHERE_COLOUR );
if ( sphere )
{
sphere.Type = ::MARKER_TYPE_VEHICLE;
Sphere = sphere.ID;
}
}

// The GTA ID of this garage
ID = 0;

// Garage position used for processing.
// This is also the sphere position inside the garage
Pos = null;

// Camera settings - we don't want the camera to be inside the garage
CamPos = null;
CamLookAt = null;

// The ID of the sphere inside the garage
Sphere = 0;

// Is the garage door open or closed?
IsOpen = false;

// Is this garage processing any vehicle at the moment?
IsProcessingVehicle = false;

// How long has the vehicle been processed? (Required by some timed stuff)
Time = 0;

// The player/vehicle who/which are being processed
Player = null;
Vehicle = null;
}

/*
 * This function initialises the garages and sets their info.
 */
function InitGarages()
{
g_Garages[ 0 ] = CPayNSpray( PORTLAND_PAYNSPRAY_GARAGE, Vector( 925.3, -361.9, 10.8 ), Vector( 925.9, -335.9, 14.3 ), Vector( 925.5, -346.4, 14.3 ) ); // Portland PnS
g_Garages[ 1 ] = CPayNSpray( STAUNTON_PAYNSPRAY_GARAGE, Vector( 382.4, -493.6, 25.7 ), Vector( 362.2, -492.2, 27.8 ), Vector( 369.6, -493.0, 27.8 ) ); // Staunton PnS
g_Garages[ 2 ] = CPayNSpray( SSV_PAYNSPRAY_GARAGE, Vector( -1144.4, 35.1, 58.8 ), Vector( -1126.2, 33.6, 61.9 ), Vector( -1132.2, 33.9, 61.3 ) ); // Shoreside PnS
}

/*
 * This func finds and returns a garage based on the sphere ID
 */
function FindGarage( sphereID )
{
for ( local i = 0; i < MAX_GARAGES; i++ )
{
if ( g_Garages[ i ].Sphere == sphereID ) return g_Garages[ i ];
}

return null;
}

/*
 * Processing of the garages. Almost everything is done here, including
 * automatic doors etc.
 */
function ProcessGarages()
{
local players = GetPlayers();

if ( !players ) return; // No point in processing if there are no players in-game

// Vars used by the processing loop
local garage = null;
local player = null, id = 0, plrs = 0;
local needsopening = false;

for ( local i = 0; i < MAX_GARAGES; i++ )
{
garage = g_Garages[ i ];

// If the garage is not processing a vehicle right now, process automatic doors
if ( !garage.IsProcessingVehicle )
{
player = null;
id = 0;
plrs = 0;
needsopening = false;

while ( id < MAX_PLAYERS && plrs < players )
{
player = FindPlayer( id );
if ( player && player.Spawned )
{
// Check if the player is within the activation radius of this garage
if ( GetDistance( player.Pos, garage.Pos ) < GARAGE_RADIUS )
{
// If so, and they're in a vehicle, flag the garage to be opened after the loop
if ( player.Vehicle ) needsopening = true;
}
plrs++;
}
id++;
}

// Process the door if needed
if ( garage.IsOpen && !needsopening )
{
CloseGarage( garage.ID );
garage.IsOpen = false;
}
else if ( !garage.IsOpen && needsopening )
{
OpenGarage( garage.ID );
garage.IsOpen = true;
}
}

// If the garage is processing a car, do some timed stuff
else
{
garage.Time++;

if ( garage.Time == 6 )
{
if ( garage.Vehicle.Health < 1000.0 )
SmallMessage( garage.Player, "~b~New engine and paint job. The cops won't recognize you!", 3000, 0 );

else SmallMessage( garage.Player, "~b~Hope you like the new color.", 3000, 0 );

PlayFrontEndSound( garage.Player, 61 );

// Fix the vehicle and respray it
garage.Vehicle.Fix();

// This should create some really funky colours
garage.Vehicle.RGBColour1 = Colour( rand() % 256, rand() % 256, rand() % 256 );
garage.Vehicle.RGBColour2 = Colour( rand() % 256, rand() % 256, rand() % 256 );

// Ready! Release the player and open the door
garage.Player.Frozen = false;

RestoreCamera( garage.Player );

garage.IsProcessingVehicle = false;
garage.Player = null;
garage.Vehicle = null;
garage.Time = 0;
garage.IsOpen = true;

OpenGarage( garage.ID );
}
}
}
}

/*
 * If the player enters a sphere we need to check whether
 * it's a garage sphere
 */
function onPlayerEnterSphere( player, sphere )
{
// Check if this is a global sphere and assigned to a garage
if ( !sphere.Owner )
{
local garage = FindGarage( sphere.ID );
if ( garage )
{
local vehicle = player.Vehicle;

// Check that the event was triggered by the vehicle driver
if ( player.ID == vehicle.Driver.ID )
{
local type = GetVehicleType( vehicle.Model );
if ( type == VEHICLE_TYPE.NORMAL )
{
// This is a normal vehicle - we can respray it

// Freeze the player
player.Frozen = true;

// Set some garage stuff for the process func
garage.IsProcessingVehicle = true;
garage.Player = player;
garage.Vehicle = player.Vehicle;
garage.IsOpen = false;

SetCameraMatrix( player, garage.CamPos, garage.CamLookAt );

CloseGarage( garage.ID );
}
else if ( type == VEHICLE_TYPE.EMERGENCY )
{
SmallMessage( player, "~b~Whoa! I don't touch nothing THAT hot!", 3000, 0 );

PlayFrontEndSound( player, 60 );
}
}
}
}

return 1;
}

/*
 * Security check that the player didn't leave while they were in a garage
 */
function onPlayerPart( player, reason )
{
local garage = null;
for ( local i = 0; i < MAX_GARAGES; i++ )
{
garage = g_Garages[ i ];

if ( garage.Player && garage.Player.ID == player.ID )
{
garage.IsProcessingVehicle = false;

garage.Player = null;
garage.Vehicle = null;

garage.Time = 0;
}
}

return 1;
}

/*
 * This function returns the type of the given vehicle model
 */
function GetVehicleType( model )
{
switch ( model )
{
// These vehicles are too big/otherwise not suitable for Pay'n'Spray. Don't process them
case VEH_LINERUNNER:
case VEH_TRASHMASTER:
case VEH_STRETCH:
case VEH_PREDATOR:
case VEH_BUS:
case VEH_TRAIN:
case VEH_DODO:
case VEH_COACH:
case VEH_RCBANDIT:
case VEH_AIRTRAIN:
case VEH_DEADDODO:
case VEH_SPEEDER:
case VEH_REEFER:
case VEH_ESCAPE:
case VEH_GHOST:
return VEHICLE_TYPE.NOTFORGARAGE;
break;

// Emergency/army vehicles - Pay'n'Spray don't want to touch nothing that hot
case VEH_FIRETRUCK:
case VEH_AMBULANCE:
case VEH_FBICAR:
case VEH_POLICE:
case VEH_ENFORCER:
case VEH_RHINO:
case VEH_BARRACKS:
return VEHICLE_TYPE.EMERGENCY;
break;

// Everything else is OK
default:
return VEHICLE_TYPE.NORMAL;
break;
}
}
Title: Re: Understanding better usages for spheres
Post by: Thijn on Aug 08, 2016, 08:06 PM
He saves the sphere ID in a variable inside the class.

So basically:

gSpheres <- array( 1, null );

gSpheres[0] = testSpheres();

class testSpheres
{
sphereId = 0;
function constructor()
{
local sphere = ::CreateSphere( pos, someradius, somecolor);
  if ( sphere )
  {
   sphereId = sphere.ID;
  }
}
}

Then you can do gSpheres[0].sphereId to get the ID.

Code is copy pasted, and probably doesn't work because how spheres are made, parameters all that shit. It should give you an idea though.
Title: Re: Understanding better usages for spheres
Post by: Mötley on Aug 08, 2016, 08:28 PM
Thank you This did give me a better idea/comprehension.


The last idea I am trying to understand is to be capable of spiting things off,

Like a bomb shop,

Or even setting a camera matrix and putting that player in a virtual world similar to MTA for gta 3 for buying weapon options.

In that case would I have to use something like
[/list][code]function onPlayerEnterSphere(player, sphere) {
if (sphere.ID == 0 ) {
etc etc

 or is there a more professional way to specify the spheres
Title: Re: Understanding better usages for spheres
Post by: ysc3839 on Aug 09, 2016, 09:54 AM
I want to know how to implement Open/CloseGarage.
Title: Re: Understanding better usages for spheres
Post by: Mötley on Aug 09, 2016, 11:34 AM
@ysc3839

http://forum.vc-mp.org/?topic=2472.msg18087#msg18087



@Thijn I still do not know how to use correct methods of many spheres and specifying them to there correct ones. So instead with pay n sprays I removed spheres and now I am checking if that player is in the vicinity, if so process the garage. "Loop methods, ;D it's not laggy as your mind would imagine, It's actually pretty clean"

This is more professional in general as even Rockstar-North does not use spheres in the PNS :D.


I'm going to attempt to continue to not use spheres for garages etc. Instead use spheres for there correct usages, like virtual worlds.