sfcnr/gamemodes/irresistible/cnr/features/gangs/cannon.pwn
2018-09-10 07:09:35 +10:00

370 lines
13 KiB
Plaintext

/*
* 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 )
{
// slay user
#if defined AC_INCLUDED
ForcePlayerKill( i, playerid, 51 );
#else
SetPlayerHealth( i, -1 );
#endif
// explode player
SendClientMessageToAllFormatted( -1, ""COL_ORANGE"[ORBITAL CANNON]"COL_WHITE" %s(%d) got rekt by %s(%d)'s orbital cannon.", ReturnPlayerName( i ), i, ReturnPlayerName( playerid ), playerid );
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;
}