363 lines
12 KiB
PHP
363 lines
12 KiB
PHP
/*
|
|
* Irresistible Gaming (c) 2018
|
|
* Developed by Lorenc Pekaj
|
|
* Module: cannon.inc
|
|
* Purpose: orbital cannon implementation for gang facilities
|
|
*/
|
|
|
|
#if !defined MAX_FACILITIES
|
|
#error "This module requires facility module!"
|
|
#endif
|
|
|
|
/* ** Includes ** */
|
|
#include < YSI\y_hooks >
|
|
|
|
/* ** Definitions ** */
|
|
#define ORBITAL_CANNON_TICK ( 100 )
|
|
|
|
/* ** Variables ** */
|
|
enum E_ORBITAL_CANNON_DATA
|
|
{
|
|
Float: E_POS[ 3 ], Float: E_ZOOM, E_TIMER,
|
|
E_FIRE_TICK, E_COOL_DOWN
|
|
};
|
|
|
|
new
|
|
g_orbitalCannonData [ MAX_FACILITIES ] [ E_ORBITAL_CANNON_DATA ],
|
|
p_usingOrbitalCannon [ MAX_PLAYERS ] = { -1, ... },
|
|
Text: g_orbitalAimTD = Text: INVALID_TEXT_DRAW,
|
|
Text3D: g_orbitalPlayerLabels [ MAX_FACILITIES ] [ MAX_PLAYERS ]
|
|
;
|
|
|
|
/* ** Hooks ** */
|
|
hook OnScriptInit( )
|
|
{
|
|
// textdraw
|
|
g_orbitalAimTD = TextDrawCreate( 305.000000, 205.000000, "+" );
|
|
TextDrawBackgroundColor( g_orbitalAimTD, 0 );
|
|
TextDrawFont( g_orbitalAimTD, 2 );
|
|
TextDrawLetterSize( g_orbitalAimTD, 1.000000, 4.000000 );
|
|
TextDrawColor( g_orbitalAimTD, -16777152 );
|
|
TextDrawSetOutline( g_orbitalAimTD, 1 );
|
|
TextDrawSetProportional( g_orbitalAimTD, 1 );
|
|
|
|
// starting data
|
|
for ( new facilityid = 0; facilityid < sizeof( g_orbitalCannonData ); facilityid ++ ) {
|
|
g_orbitalCannonData[ facilityid ] [ E_TIMER ] = -1;
|
|
for ( new i = 0; i < sizeof( g_orbitalPlayerLabels[ ] ); i ++ ) {
|
|
g_orbitalPlayerLabels[ facilityid ] [ i ] = Text3D: INVALID_3DTEXT_ID;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
hook SetPlayerRandomSpawn( playerid )
|
|
{
|
|
if ( GetPVarType( playerid, "left_cannon" ) != PLAYER_VARTYPE_NONE )
|
|
{
|
|
new facilityid = GetPVarInt( playerid, "left_cannon" );
|
|
new int_type = g_gangFacilities[ facilityid ] [ E_INTERIOR_TYPE ];
|
|
|
|
// place in facility
|
|
pauseToLoad( playerid );
|
|
SetPVarInt( playerid, "in_facility", facilityid );
|
|
UpdatePlayerEntranceExitTick( playerid );
|
|
SetPlayerPos( playerid, g_gangFacilityInterior[ int_type ] [ E_CANNON_POS ] [ 0 ], g_gangFacilityInterior[ int_type ] [ E_CANNON_POS ] [ 1 ], g_gangFacilityInterior[ int_type ] [ E_CANNON_POS ] [ 2 ] );
|
|
SetPlayerVirtualWorld( playerid, g_gangFacilities[ facilityid ] [ E_WORLD ] );
|
|
SetPlayerInterior( playerid, 0 );
|
|
|
|
// set camera
|
|
DeletePVar( playerid, "left_cannon" );
|
|
SetCameraBehindPlayer( playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerDisconnect( playerid, reason )
|
|
{
|
|
ClosePlayerOrbitalCannon( playerid );
|
|
return 1;
|
|
}
|
|
|
|
#if defined AC_INCLUDED
|
|
hook OnPlayerDeathEx( playerid, killerid, reason, Float: damage, bodypart )
|
|
#else
|
|
hook OnPlayerDeath(playerid, killerid, reason)
|
|
#endif
|
|
{
|
|
ClosePlayerOrbitalCannon( playerid );
|
|
return 1;
|
|
}
|
|
|
|
/* ** Callbacks ** */
|
|
function OnPlayerOrbitalCannonUpdate( facilityid, playerid )
|
|
{
|
|
new Float: current_pos[ 3 ];
|
|
new Float: move_unit = 10.0;
|
|
new keys, ud, lr;
|
|
|
|
GetPlayerKeys( playerid, keys, ud, lr );
|
|
|
|
// store local positions
|
|
current_pos[ 0 ] = g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ];
|
|
current_pos[ 1 ] = g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ];
|
|
MapAndreas_FindZ_For2DCoord( current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ] );
|
|
|
|
// close
|
|
if ( ( keys & KEY_CROUCH ) || IsPlayerJailed( playerid ) || IsPlayerAFK( playerid ) || ( GetPlayerCash( playerid ) < 250000 && ! g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] ) )
|
|
{
|
|
SetPVarInt( playerid, "left_cannon", facilityid );
|
|
HidePlayerHelpDialog( playerid );
|
|
if ( IsPlayerMovieMode( playerid ) ) cmd_moviemode( playerid, "" );
|
|
ClosePlayerOrbitalCannon( playerid );
|
|
return TogglePlayerSpectating( playerid, 0 );
|
|
}
|
|
|
|
// fire ammo
|
|
if ( ( keys & KEY_SPRINT ) && ! g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] )
|
|
{
|
|
// add tick (ms) for countdown
|
|
g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] += ORBITAL_CANNON_TICK;
|
|
|
|
// just pressed fire? move camera
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] == ORBITAL_CANNON_TICK ) {
|
|
// smoothly move camera
|
|
InterpolateCameraPos(
|
|
playerid,
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ],
|
|
current_pos[ 2 ] + g_orbitalCannonData[ facilityid ] [ E_ZOOM ],
|
|
current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ] + g_orbitalCannonData[ facilityid ] [ E_ZOOM ] + 50.0,
|
|
5000
|
|
);
|
|
|
|
InterpolateCameraLookAt(
|
|
playerid,
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ], current_pos[ 2 ],
|
|
current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ],
|
|
5000
|
|
);
|
|
}
|
|
|
|
// alert
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] % 1000 == 0 )
|
|
{
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] > 3000 )
|
|
{
|
|
g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] = 0;
|
|
g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] = ORBITAL_CANNON_TICK * 20;
|
|
|
|
new rocket = CreateDynamicObject( 3786, current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ] + g_orbitalCannonData[ facilityid ] [ E_ZOOM ], 5.0, -90.0, 0.0 );
|
|
new move_speed = MoveDynamicObject( rocket, current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ], 100.0 );
|
|
Streamer_Update( playerid, STREAMER_TYPE_OBJECT );
|
|
|
|
GivePlayerCash( playerid, -250000 );
|
|
PlayerPlaySound( playerid, 1057, 0.0, 0.0, 0.0 );
|
|
GameTextForPlayer( playerid, "~g~FIRED!", 2000, 3 );
|
|
SendServerMessage( playerid, "You have launched an orbital cannon for "COL_GOLD"$250,000"COL_WHITE", you have %s left.", number_format( GetPlayerCash( playerid ) ) );
|
|
return SetTimerEx( "OnPlayerFireOrbitalCannon", move_speed, false, "ddfff", playerid, rocket, current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ] );
|
|
}
|
|
else
|
|
{
|
|
g_orbitalCannonData[ facilityid ] [ E_ZOOM ] += 2.0;
|
|
GameTextForPlayer( playerid, sprintf( "~r~%d", g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] / 1000 ), 2000, 3 );
|
|
PlayerPlaySound( playerid, 1056, 0.0, 0.0, 0.0 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] = 0;
|
|
}
|
|
|
|
// deduct cooldown
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] && ( g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] -= ORBITAL_CANNON_TICK ) <= 0 )
|
|
g_orbitalCannonData[ facilityid ] [ E_COOL_DOWN ] = 0;
|
|
|
|
// begin movement
|
|
if ( ! g_orbitalCannonData[ facilityid ] [ E_FIRE_TICK ] )
|
|
{
|
|
// zoom in
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_ZOOM ] > 75.0 ) move_unit = g_orbitalCannonData[ facilityid ] [ E_ZOOM ] / 7.5;
|
|
else if ( g_orbitalCannonData[ facilityid ] [ E_ZOOM ] <= 20.0 ) move_unit = 5.0;
|
|
|
|
// move camera
|
|
if ( ud == KEY_UP ) current_pos[ 1 ] += move_unit;
|
|
else if ( ud == KEY_DOWN ) current_pos[ 1 ] -= move_unit;
|
|
|
|
if ( lr == KEY_LEFT ) current_pos[ 0 ] -= move_unit;
|
|
else if ( lr == KEY_RIGHT ) current_pos[ 0 ] += move_unit;
|
|
|
|
// zoom in
|
|
if ( keys & KEY_FIRE ) {
|
|
if ( ( g_orbitalCannonData[ facilityid ] [ E_ZOOM ] -= move_unit ) < 20.0 ) {
|
|
g_orbitalCannonData[ facilityid ] [ E_ZOOM ] = 20.0;
|
|
}
|
|
}
|
|
else if ( keys & KEY_AIM ) {
|
|
if ( ( g_orbitalCannonData[ facilityid ] [ E_ZOOM ] += move_unit ) > 300.0 ) {
|
|
g_orbitalCannonData[ facilityid ] [ E_ZOOM ] = 300.0;
|
|
}
|
|
}
|
|
|
|
// smoothly move camera
|
|
InterpolateCameraPos(
|
|
playerid,
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 2 ] + g_orbitalCannonData[ facilityid ] [ E_ZOOM ],
|
|
current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ] + g_orbitalCannonData[ facilityid ] [ E_ZOOM ],
|
|
150
|
|
);
|
|
|
|
InterpolateCameraLookAt(
|
|
playerid,
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ], g_orbitalCannonData[ facilityid ] [ E_POS ] [ 2 ],
|
|
current_pos[ 0 ], current_pos[ 1 ], current_pos[ 2 ],
|
|
150
|
|
);
|
|
}
|
|
|
|
// update
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] = current_pos;
|
|
return 1;
|
|
}
|
|
|
|
function OnPlayerFireOrbitalCannon( playerid, rocketid, Float: X, Float: Y, Float: Z )
|
|
{
|
|
new Float: player_X, Float: player_Y, Float: player_Z;
|
|
|
|
// destroy the rocket after it is moved
|
|
DestroyDynamicObject( rocketid );
|
|
|
|
// kill everyone in that area
|
|
foreach ( new i : Player ) if ( GetPlayerGang( i ) != GetPlayerGang( playerid ) && GetPlayerVirtualWorld( i ) == 0 && GetPlayerInterior( i ) == 0 && ! IsPlayerJailed( i ) && ! IsPlayerAdminOnDuty( i ) && ! IsPlayerSpawnProtected( i ) )
|
|
{
|
|
new
|
|
player_state = GetPlayerState( i );
|
|
|
|
if ( GetPlayerPos( i, player_X, player_Y, player_Z ) && player_Z >= Z && player_state != PLAYER_STATE_WASTED && player_state != PLAYER_STATE_SPECTATING )
|
|
{
|
|
new
|
|
Float: distance_squared = VectorSize( player_X - X, player_Y - Y, 0.0 );
|
|
|
|
if ( distance_squared < 30.0 )
|
|
{
|
|
SendClientMessageToAllFormatted( -1, ""COL_ORANGE"[ORBITAL CANNON]"COL_WHITE" %s(%d) got rekt by %s(%d)'s orbital cannon.", ReturnPlayerName( i ), i, ReturnPlayerName( playerid ), playerid );
|
|
ForcePlayerKill( i, playerid, 51 );
|
|
CreateExplosion( player_X, player_Y, player_Z, 0, 10.0 );
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// create explosion
|
|
CreateExplosion( X, Y, Z, 6, 10.0 );
|
|
return 1;
|
|
}
|
|
|
|
/* ** Functions ** */
|
|
stock StartPlayerOrbitalCannon( playerid, facilityid )
|
|
{
|
|
if ( g_orbitalCannonData[ facilityid ] [ E_TIMER ] != -1 )
|
|
return 0;
|
|
|
|
// player
|
|
SetPlayerInterior( playerid, 0 );
|
|
SetPlayerVirtualWorld( playerid, 0 );
|
|
TogglePlayerSpectating( playerid, 1 );
|
|
TextDrawShowForPlayer( playerid, g_orbitalAimTD );
|
|
ShowPlayerHelpDialog( playerid, 0, "~y~Arrows~w~ - Move camera~n~~y~~k~~PED_FIREWEAPON~~w~ - Zoom in~n~~y~~k~~PED_LOCK_TARGET~~w~ - Zoom out~n~~y~~k~~PED_SPRINT~~w~ - Fire cannon ~g~($250,000)~n~~y~~k~~PED_DUCK~~w~ - Cancel" );
|
|
p_usingOrbitalCannon[ playerid ] = facilityid;
|
|
if ( ! IsPlayerMovieMode( playerid ) ) cmd_moviemode( playerid, "" );
|
|
|
|
// destroy labels (created on stream out/in anyway)
|
|
for ( new i = 0; i < sizeof( g_orbitalPlayerLabels[ ] ); i ++ ) {
|
|
DestroyDynamic3DTextLabel( g_orbitalPlayerLabels[ facilityid ] [ i ] );
|
|
g_orbitalPlayerLabels[ facilityid ] [ i ] = Text3D: INVALID_3DTEXT_ID;
|
|
}
|
|
|
|
// set cannon position
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 0 ] = g_gangFacilities[ facilityid ] [ E_X ];
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 1 ] = g_gangFacilities[ facilityid ] [ E_Y ];
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 2 ] = g_gangFacilities[ facilityid ] [ E_Z ];
|
|
|
|
// set zoom of camera
|
|
g_orbitalCannonData[ facilityid ] [ E_POS ] [ 2 ] += ( g_orbitalCannonData[ facilityid ] [ E_ZOOM ] += 100.0 );
|
|
|
|
g_orbitalCannonData[ facilityid ] [ E_TIMER ] = SetTimerEx( "OnPlayerOrbitalCannonUpdate", ORBITAL_CANNON_TICK, true, "dd", facilityid, playerid );
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerStreamIn( playerid, forplayerid )
|
|
{
|
|
if ( ! IsPlayerNPC( playerid ) && IsPlayerUsingOrbitalCannon( forplayerid ) )
|
|
{
|
|
new
|
|
facilityid = p_usingOrbitalCannon[ forplayerid ];
|
|
|
|
if ( 0 <= facilityid < sizeof( g_orbitalCannonData ) )
|
|
{
|
|
if ( ! IsValidDynamic3DTextLabel( g_orbitalPlayerLabels[ facilityid ] [ playerid ] ) )
|
|
{
|
|
g_orbitalPlayerLabels[ facilityid ] [ playerid ] = CreateDynamic3DTextLabel(
|
|
sprintf( "%s(%d)", ReturnPlayerName( playerid ), playerid ),
|
|
setAlpha( GetPlayerColor( playerid ), 0xFF ),
|
|
0.0, 0.0, 0.0, 300.0,
|
|
.attachedplayer = playerid,
|
|
.testlos = 0,
|
|
.playerid = forplayerid,
|
|
.streamdistance = 300.0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerStreamOut( playerid, forplayerid )
|
|
{
|
|
if ( ! IsPlayerNPC( playerid ) && IsPlayerUsingOrbitalCannon( forplayerid ) )
|
|
{
|
|
new
|
|
facilityid = p_usingOrbitalCannon[ forplayerid ];
|
|
|
|
if ( 0 <= facilityid < sizeof( g_orbitalCannonData ) )
|
|
{
|
|
if ( IsValidDynamic3DTextLabel( g_orbitalPlayerLabels[ facilityid ] [ playerid ] ) )
|
|
{
|
|
DestroyDynamic3DTextLabel( g_orbitalPlayerLabels[ facilityid ] [ playerid ] );
|
|
g_orbitalPlayerLabels[ facilityid ] [ playerid ] = Text3D: INVALID_3DTEXT_ID;
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
stock ClosePlayerOrbitalCannon( playerid ) {
|
|
|
|
new
|
|
facilityid = p_usingOrbitalCannon[ playerid ];
|
|
|
|
// remove user
|
|
p_usingOrbitalCannon[ playerid ] = -1;
|
|
TextDrawHideForPlayer( playerid, g_orbitalAimTD );
|
|
|
|
// reset facility portion
|
|
if ( 0 <= facilityid < sizeof( g_orbitalCannonData ) )
|
|
{
|
|
// remove label associated
|
|
for ( new i = 0; i < sizeof( g_orbitalPlayerLabels[ ] ); i ++ ) {
|
|
DestroyDynamic3DTextLabel( g_orbitalPlayerLabels[ facilityid ] [ i ] );
|
|
g_orbitalPlayerLabels[ facilityid ] [ i ] = Text3D: INVALID_3DTEXT_ID;
|
|
}
|
|
|
|
// kill timer
|
|
KillTimer( g_orbitalCannonData[ facilityid ] [ E_TIMER ] );
|
|
g_orbitalCannonData[ facilityid ] [ E_TIMER ] = -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
stock IsPlayerUsingOrbitalCannon( playerid ) {
|
|
return p_usingOrbitalCannon[ playerid ] != -1;
|
|
}
|