Junior Member
|
07-30-2014
, 06:40
Re: Blockmaker - Adding Blocks (12 Step) In-Depth | Updated 12/24/2013!
|
#289
|
well,sorry for bumping this up,but i really need help here
can someone post a code showing how to add bhop block with no underblock feature + a chat message when someone actually tries to underblock/underknife
example: [Prefix] Player#1 tried to Underknife Player#2
would be awesome if someone would do this for me
here is the plugin to add the code in :
Code:
#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fun>
#include <cstrike>
#include <fakemeta>
#include <colorchat>
#include <dhudmessage>
#pragma semicolon 1;
#define PLUGIN "iGz Blockmaker"
#define VERSION "0.5.0"
#define AUTHOR "Koleos" // wishes he could code somethin like this..
#define BM_ADMIN_LEVEL ADMIN_RCON //admin access level to use this plugin. ADMIN_BAN = flag 'b' , or change value for ADMIN_MENU = 'u'
new ScoutUsed[42];
new ShotgunUsed[42];
new DEagleUsed[42];
new AwpUsed[42];
new HeUsed[42];
new FlashUsed[42];
new FrostUsed[42];
new Ak47Used[42];
new M4a1Used[42];
new UspUsed[42];
new FamasUsed[42];
new GlockUsed[42];
new P90Used[42];
new GalilUsed[42];
#define HE 0
#define SMOKE 1
#define FLASH 2
new grenade_taken[3][42];
new gKeysMainMenu;
new gKeysBlockMenu;
new gKeysBlockSelectionMenu;
new gKeysTeleportMenu;
new gKeysOptionsMenu;
new gKeysChoiceMenu;
const Float:gfSnapDistance = 10.0; //blocks snap together when they're within this value + the players snap gap
// enum for menu option values
enum
{
N1, N2, N3, N4, N5, N6, N7, N8, N9, N0
};
// enum for bit-shifted numbers 1 - 10
enum
{
B1 = 1 << N1, B2 = 1 << N2, B3 = 1 << N3, B4 = 1 << N4, B5 = 1 << N5,
B6 = 1 << N6, B7 = 1 << N7, B8 = 1 << N8, B9 = 1 << N9, B0 = 1 << N0,
};
// enum for options with YES/NO confirmation
enum
{
CHOICE_LOAD,
CHOICE_DEL_BLOCKS,
CHOICE_DEL_TELEPORTS
};
// enum for different block sizes
enum
{
NORMAL,
SMALL,
LARGE,
POLE
};
// enum for axes
enum
{
X,
Y,
Z
};
// block scales
const Float:SCALE_SMALL = 0.25;
const Float:SCALE_NORMAL = 1.0;
const Float:SCALE_LARGE = 2.0;
const Float:SCALE_LJPOLE = 0.125;
// hud message values
const gHudRed = 255;
const gHudGreen = 125;
const gHudBlue = 0;
const Float:gfTextX = -1.0;
const Float:gfTextY = 0.84;
const gHudEffects = 0;
const Float:gfHudFxTime = 0.75;
const Float:gfHudHoldTime = 0.75;
const Float:gfHudFadeInTime = 0.75;
const Float:gfHudFadeOutTime = 0.75;
const gHudChannel = 2;
// Task ID offsets
const TASK_BHOPSOLID = 1000;
const TASK_BHOPSOLIDNOT = 2000;
const TASK_INVINCIBLE = 3000;
const TASK_STEALTH = 4000;
const TASK_ICE = 5000;
const TASK_SPRITE = 6000;
const TASK_CAMOUFLAGE = 7000;
const TASK_HONEY = 8000;
const TASK_FIRE = 9000;
const TASK_BOOTSOFSPEED = 10000;
const TASK_TELEPORT = 11000;
const TASK_NOSLOW = 12000;
const TASK_SUPERMAN = 13000;
// strings
new const gszPrefix[] = "[staNioN-MM]";
new const gszInfoTarget[] = "info_target";
new const gszHelpFilenameFormat[] = "blockmaker_v%s.txt";
new gszFile[128];
new gszNewFile[128];
new gszMainMenu[256];
new gszBlockMenu[256];
new gszTeleportMenu[256];
new gszOptionsMenu[256];
new gszChoiceMenu[128];
new gszHelpTitle[64];
new gszHelpText[1600];
new gszHelpFilename[32];
new gszViewModel[33][32];
// block dimensions
new Float:gfBlockSizeMinForX[3] = {-4.0,-32.0,-32.0};
new Float:gfBlockSizeMaxForX[3] = { 4.0, 32.0, 32.0};
new Float:gfBlockSizeMinForY[3] = {-32.0,-4.0,-32.0};
new Float:gfBlockSizeMaxForY[3] = { 32.0, 4.0, 32.0};
new Float:gfBlockSizeMinForZ[3] = {-32.0,-32.0,-4.0};
new Float:gfBlockSizeMaxForZ[3] = { 32.0, 32.0, 4.0};
new Float:gfDefaultBlockAngles[3] = { 0.0, 0.0, 0.0 };
// pole block dimensions
new Float:gfPoleBlockSizeMinForX[3] = {-32.0,-4.0,-4.0};
new Float:gfPoleBlockSizeMaxForX[3] = { 32.0, 4.0, 4.0};
new Float:gfPoleBlockSizeMinForZ[3] = {-4.0,-4.0,-32.0};
new Float:gfPoleBlockSizeMaxForZ[3] = { 4.0, 4.0, 32.0};
new Float:gfPoleBlockSizeMinForY[3] = {-4.0,-32.0,-4.0};
new Float:gfPoleBlockSizeMaxForY[3] = { 4.0, 32.0, 4.0};
// block models
new const gszBlockModelDefault[] = "models/blockmaker/bm_block_default.mdl";
new const gszBlockModelPlatform[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelBhop[] = "models/blockmaker/igz_bhopV5.mdl";
new const gszBlockModelDamage[] = "models/blockmaker/igz_damage.mdl";
new const gszBlockModelHealer[] = "models/blockmaker/igz_health.mdl";
new const gszBlockModelInvincibility[] = "models/blockmaker/igz_invincibility.mdl";
new const gszBlockModelStealth[] = "models/blockmaker/igz_stealth.mdl";
new const gszBlockModelSpeedBoost[] = "models/blockmaker/igz_speedboost.mdl";
new const gszBlockModelNoFallDamage[] = "models/blockmaker/igz_nofalldamage.mdl";
new const gszBlockModelIce[] = "models/blockmaker/igz_ice.mdl";
new const gszBlockModelDeath[] = "models/blockmaker/igz_death.mdl";
new const gszBlockModelCamouflage[] = "models/blockmaker/igz_camouflage.mdl";
new const gszBlockModelLowGravity[] = "models/blockmaker/bm_block_lowgravity.mdl";
new const gszBlockModelFire[] = "models/blockmaker/igz_fire.mdl";
new const gszBlockModelRandom[] = "models/blockmaker/igz_random.mdl";
new const gszBlockModelSlap[] = "models/blockmaker/igz_slapV2.mdl";
new const gszBlockModelHoney[] = "models/blockmaker/igz_honey.mdl";
new const gszBlockModelBarrierCT[] = "models/blockmaker/igz_ct_barrier.mdl";
new const gszBlockModelBarrierT[] = "models/blockmaker/igz_t_barrier.mdl";
new const gszBlockModelBootsOfSpeed[] = "models/blockmaker/igz_boostofspeedV2.mdl";
new const gszBlockModelGlass[] = "models/NextGen/NextGen_Glass.mdl";
new const gszBlockModelGlass_igz[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelGlass_Normal[] = "models/NextGen/NextGen_Glass.mdl";
new const gszBlockModelBhopNoSlow[] = "models/blockmaker/igz_bhopV5.mdl";
new const gszBlockModelDelayedBhop[] = "models/blockmaker/igz_delay_bhop.mdl";
new const gszBlockModelFade[] = "models/blockmaker/igz_blind.mdl";
new const gszBlockModelDEagle[] = "models/blockmaker/igz_deagle.mdl";
new const gszBlockModelHe[] = "models/blockmaker/igz_grenade.mdl";
new const gszBlockModelSmoke[] = "models/blockmaker/igz_frostblock.mdl";
new const gszBlockModelFlash[] = "models/blockmaker/igz_flashnade.mdl";
new const gszBlockModelAwp[] = "models/blockmaker/igz_gun_awp.mdl";
new const gszBlockModelTrampolineLow[] = "models/blockmaker/igz_trampoline.mdl";
new const gszBlockModelTrampolineMid[] = "models/blockmaker/igz_trampoline.mdl";
new const gszBlockModelTrampolineHigh[] = "models/blockmaker/igz_trampoline.mdl";
new const gszBlockModelLight[] = "models/blockmaker/bm_block_default.mdl";
new const gszBlockModelNoFallDamageBhop[] = "models/blockmaker/bm_block_default.mdl";
new const gszBlockModelDuck[] = "models/blockmaker/igz_duck.mdl";
new const gszBlockModelMoney[] = "models/blockmaker/igz_money.mdl";
new const gszBlockModelSuperman[] = "models/blockmaker/igz_superman.mdl";
new const gszBlockModelXP[] = "models/outrun/XP.mdl";
new const gszBlockModelShotgun[] = "models/NextGen/NextGen_Shotgun.mdl";
new const gszBlockModelScout[] = "models/blockmaker/mokescout.mdl";
new const gszBlockModelAk47[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelM4a1[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelUsp[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelFamas[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelGlock[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelP90[] = "models/blockmaker/igz_platformv2.mdl";
new const gszBlockModelGalil[] = "models/blockmaker/igz_platformv2.mdl";
// block sounds
new const gszFireSoundFlame[] = "ambience/flameburst1.wav"; //from HL
new const gszInvincibleSound[] = "warcraft3/divineshield.wav"; //from WC3 plugin
new const gszCamouflageSound[] = "warcraft3/antend.wav"; //from WC3 plugin
new const gszStealthSound[] = "warcraft3/levelupcaster.wav"; //from WC3 plugin
new const gszBootsOfSpeedSound[] = "warcraft3/purgetarget1.wav"; //from WC3 plugin
// teleport
new const Float:gfTeleportSizeMin[3] = {-16.0,-16.0,-16.0};
new const Float:gfTeleportSizeMax[3] = { 16.0, 16.0, 16.0};
new const Float:gfTeleportZOffset = 36.0;
new const gTeleportStartFrames = 20;
new const gTeleportEndFrames = 5;
new const gszTeleportSound[] = "warcraft3/blinkarrival.wav"; //from WC3 plugin
new const gszTeleportSpriteStart[] = "sprites/flare6.spr"; //from HL
new const gszTeleportSpriteEnd[] = "sprites/blockmaker/bm_teleport_end.spr"; //custom
// global variables
new gSpriteIdBeam;
new gSpriteIdFire;
new gMsgScreenFade;
new gBlockSize[33];
new gMenuBeforeOptions[33];
new gChoiceOption[33];
new gBlockMenuPage[33];
new gTeleportStart[33];
new gGrabbed[33];
new gGroupedBlocks[33][256];
new gGroupCount[33];
// global booleans
new bool:gbSnapping[33];
new bool:gbNoFallDamage[33];
new bool:gbNoFallDamageBhop[33];
new bool:gbOnIce[33];
new bool:gbNoSlowDown[33];
new bool:gbLowGravity[33];
new bool:gbOnFire[33];
new bool:gbJustDeleted[33];
new bool:gbAdminGodmode[33];
new bool:gbAdminNoclip[33];
// global floats
new Float:gfSnappingGap[33];
new Float:gfOldMaxSpeed[33];
new Float:gfGrablength[33];
new Float:gfNextHealTime[33];
new Float:gfNextDamageTime[33];
new Float:gfInvincibleNextUse[33];
new Float:gfInvincibleTimeOut[33];
new Float:gfStealthNextUse[33];
new Float:gfStealthTimeOut[33];
new Float:gfTrampolineTimeout[33];
new Float:gfSpeedBoostTimeOut[33];
new Float:gfTrampolineMidTimeout[42];
new Float:gfTrampolineLowTimeout[42];
new Float:gfCamouflageNextUse[33];
new Float:gfCamouflageTimeOut[33];
new Float:gfRandomNextUse[33];
new Float:gfBootsOfSpeedTimeOut[33];
new Float:gfBootsOfSpeedNextUse[33];
new Float:gfMoneyNextUse[33];
new Float:gfSupermanTimeOut[33];
new Float:gfSupermanNextUse[33];
new Float:gfXPNextUse[33];
// global vectors
new Float:gvGrabOffset[33][3];
// global strings
new gszCamouflageOldModel[33][32];
// block & teleport types
const gBlockMax = 48;
new gSelectedBlockType[gBlockMax];
new gRender[gBlockMax];
new gRed[gBlockMax];
new gGreen[gBlockMax];
new gBlue[gBlockMax];
new gAlpha[gBlockMax];
new const gszBlockClassname[] = "bm_block";
new const gszSpriteClassname[] = "bm_sprite";
new const gszTeleportStartClassname[] = "bm_teleport_start";
new const gszTeleportEndClassname[] = "bm_teleport_end";
enum
{
TELEPORT_START,
TELEPORT_END
};
enum
{
BM_PLATFORM, //A
BM_BHOP, //B
BM_DAMAGE, //C
BM_HEALER, //D
BM_NOFALLDAMAGE, //I
BM_ICE, //J
BM_SPEEDBOOST, //H
BM_INVINCIBILITY, //E
BM_STEALTH, //F
BM_DEATH, //K
BM_CAMOUFLAGE, //M
BM_LOWGRAVITY, //N
BM_FIRE, //O
BM_SLAP, //P
BM_RANDOM, //Q
BM_HONEY, //R
BM_BARRIER_CT, //S
BM_BARRIER_T, //T
BM_BOOTSOFSPEED, //U
BM_GLASS, //V
BM_GLASS_IGZ, //X
BM_GLASS_NORMAL, // +
BM_BHOP_NOSLOW, //W
BM_DELAYEDBHOP, //$
BM_FADE, // <
BM_DEAGLE, // #
BM_HE, // Y
BM_SMOKE, // Z
BM_FLASH, // !
BM_AWP, // @
BM_TRAMPOLINE_LOW, // =
BM_TRAMPOLINE_MID, // G
BM_TRAMPOLINE_HIGH, // )
BM_LIGHT, // (
BM_NOFALLDAMAGEBHOP, // 4
BM_DUCK, // 9
BM_MONEY, // 7
BM_SUPERMAN, //8
BM_XP, // &
BM_SHOTGUN, // 2
BM_SCOUT, // 3
BM_AK47, // >
BM_M4A1, // ]
BM_USP, // [
BM_FAMAS , // .
BM_GLOCK, // _
BM_P90, // ?
BM_GALIL // |
}
enum
{
NORMAL,
GLOWSHELL,
TRANSCOLOR,
TRANSALPHA,
TRANSWHITE
};
new const gszBlockNames[gBlockMax][47] =
{
"Platform",
"Bunnyhop",
"Damage",
"Healer",
"No Fall Damage",
"Ice",
"Speed Boost",
"Invincibility",
"Stealth",
"Death",
"Camouflage",
"Low Gravity",
"Fire",
"Slap",
"Random",
"Honey",
"CT Barrier",
"T Barrier",
"Boots Of Speed",
"Glass",
"Glass_igz",
"Glass_Normal",
"Bunnyhop [No slow down]",
"Delayed Bhop",
"Blind [Trap]",
"Deagle [Block]",
"He Grenade",
"Frost Grenade",
"Flash Grenade",
"Awp [Block]",
"Trampoline [Low]",
"Trampoline",
"Trampoline [High]",
"Light",
"No Fall Damage [Bhop]",
"Duck",
"Money",
"Superman",
"XP [Block]",
"Shotgun [Block]",
"Scout [Block]",
"Ak47 [Block]",
"M4a1 [Block]",
"USP [Block]",
"Famas [Block]",
"Glock [Block]",
"P90 [Block]",
"Galil [Block]"
};
// save IDs
new const gBlockSaveIds[gBlockMax] =
{
'A', 'B', 'C', 'D', 'I', 'J', 'H', 'E', 'F', 'K', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', '+', '$', '<', '#', 'Y', 'Z', '!', '@', '=', 'G', ')', '(', '4', '9', '7', '8', '&', '2', '3', '>', ']', '[', '.', '_', '?', '|'
};
const gTeleportSaveId = '*';
//global array of strings to store the paths and filenames to the block models
new gszBlockModels[gBlockMax][256];
//array of blocks that the random block can be
const gRandomBlocksMax = 17;
new const gRandomBlocks[gRandomBlocksMax] =
{
BM_INVINCIBILITY,
BM_STEALTH,
BM_DEATH,
BM_CAMOUFLAGE,
BM_SLAP,
BM_BOOTSOFSPEED,
BM_DEAGLE,
BM_SHOTGUN,
BM_SCOUT,
BM_AWP,
BM_AK47,
BM_M4A1,
BM_USP,
BM_FAMAS,
BM_GLOCK,
BM_P90,
BM_GALIL
};
//max speed for player when they have the boots of speed
const Float:gfBootsMaxSpeed = 400.0;
//how many pages for the block selection menu
new gBlockMenuPagesMax;
/***** PLUGIN START *****/
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR);
register_cvar(PLUGIN, VERSION, FCVAR_SERVER, 0.0);
//register client commands
register_clcmd("say /bm", "showMainMenu", ADMIN_RCON);
register_clcmd("+bmgrab", "cmdGrab", BM_ADMIN_LEVEL, "bind a key to +bmgrab");
register_clcmd("-bmgrab", "cmdRelease", BM_ADMIN_LEVEL);
//register forwards
register_forward(FM_EmitSound, "forward_EmitSound");
//create the menus
createMenus();
//register menus
register_menucmd(register_menuid("bmMainMenu"), gKeysMainMenu, "handleMainMenu");
register_menucmd(register_menuid("bmBlockMenu"), gKeysBlockMenu, "handleBlockMenu");
register_menucmd(register_menuid("bmBlockSelectionMenu"), gKeysBlockSelectionMenu, "handleBlockSelectionMenu");
register_menucmd(register_menuid("bmTeleportMenu"), gKeysTeleportMenu, "handleTeleportMenu");
register_menucmd(register_menuid("bmOptionsMenu"), gKeysOptionsMenu, "handleOptionsMenu");
register_menucmd(register_menuid("bmChoiceMenu"), gKeysChoiceMenu, "handleChoiceMenu");
//register CVARs
register_cvar("bm_telefrags", "0"); //players near teleport exit die if someone comes through
register_cvar("bm_firedamageamount", "20.0"); //damage you take per half-second on the fire block
register_cvar("bm_damageamount", "5.0"); //damage you take per half-second on the damage block
register_cvar("bm_healamount", "1.0"); //how much hp per half-second you get on the healing block
register_cvar("bm_invincibletime", "20.0"); //how long a player is invincible
register_cvar("bm_invinciblecooldown", "60.0"); //time before the invincible block can be used again
register_cvar("bm_stealthtime", "20.0"); //how long a player is in stealth
register_cvar("bm_stealthcooldown", "60.0"); //time before the stealth block can be used again
register_cvar("bm_camouflagetime", "20.0"); //how long a player is in camouflage
register_cvar("bm_camouflagecooldown", "60.0"); //time before the camouflage block can be used again
register_cvar("bm_randomcooldown", "30.0"); //time before the random block can be used again
register_cvar("bm_bootsofspeedtime", "20.0"); //how long the player has boots of speed
register_cvar("bm_bootsofspeedcooldown", "60.0"); //time before boots of speed can be used again
register_cvar("bm_teleportsound", "1"); //teleporters make sound
register_cvar("bm_moneycooldown", "9999.0"); // how long until you can use money again
register_cvar("bm_supermantime", "15.0");
register_cvar("bm_supermancooldown", "60.0");
register_cvar("bm_xpcooldown", "999.0");
//register events
register_event("DeathMsg", "eventPlayerDeath", "a");
register_event("TextMsg", "eventRoundRestart", "a", "2&#Game_C", "2&#Game_w");
register_event("ResetHUD", "eventPlayerSpawn", "b");
register_event("CurWeapon", "eventCurWeapon", "be");
register_logevent("eventRoundRestart", 2, "1=Round_Start");
//make save folder in basedir (new saving/loading method)
new szDir[64];
new szMap[32];
get_basedir(szDir, 64);
add(szDir, 64, "/blockmaker");
//make config folder if it doesn't already exist
if (!dir_exists(szDir))
{
mkdir(szDir);
}
get_mapname(szMap, 32);
formatex(gszNewFile, 96, "%s/%s.bm", szDir, szMap);
}
public plugin_precache()
{
//set block models to defaults
gszBlockModels[BM_PLATFORM] = gszBlockModelPlatform;
gszBlockModels[BM_BHOP] = gszBlockModelBhop;
gszBlockModels[BM_DAMAGE] = gszBlockModelDamage;
gszBlockModels[BM_HEALER] = gszBlockModelHealer;
gszBlockModels[BM_NOFALLDAMAGE] = gszBlockModelNoFallDamage;
gszBlockModels[BM_ICE] = gszBlockModelIce;
gszBlockModels[BM_SPEEDBOOST] = gszBlockModelSpeedBoost;
gszBlockModels[BM_INVINCIBILITY] = gszBlockModelInvincibility;
gszBlockModels[BM_STEALTH] = gszBlockModelStealth;
gszBlockModels[BM_DEATH] = gszBlockModelDeath;
gszBlockModels[BM_CAMOUFLAGE] = gszBlockModelCamouflage;
gszBlockModels[BM_LOWGRAVITY] = gszBlockModelLowGravity;
gszBlockModels[BM_FIRE] = gszBlockModelFire;
gszBlockModels[BM_SLAP] = gszBlockModelSlap;
gszBlockModels[BM_RANDOM] = gszBlockModelRandom;
gszBlockModels[BM_HONEY] = gszBlockModelHoney;
gszBlockModels[BM_BARRIER_CT] = gszBlockModelBarrierCT;
gszBlockModels[BM_BARRIER_T] = gszBlockModelBarrierT;
gszBlockModels[BM_BOOTSOFSPEED] = gszBlockModelBootsOfSpeed;
gszBlockModels[BM_GLASS] = gszBlockModelGlass;
gszBlockModels[BM_GLASS_IGZ] = gszBlockModelGlass_igz;
gszBlockModels[BM_GLASS_NORMAL] = gszBlockModelGlass_Normal;
gszBlockModels[BM_BHOP_NOSLOW] = gszBlockModelBhopNoSlow;
gszBlockModels[BM_DELAYEDBHOP] = gszBlockModelDelayedBhop;
gszBlockModels[BM_FADE] = gszBlockModelFade;
gszBlockModels[BM_DEAGLE] = gszBlockModelDEagle;
gszBlockModels[BM_HE] = gszBlockModelHe;
gszBlockModels[BM_SMOKE] = gszBlockModelSmoke;
gszBlockModels[BM_FLASH] = gszBlockModelFlash;
gszBlockModels[BM_AWP] = gszBlockModelAwp;
gszBlockModels[BM_TRAMPOLINE_LOW] = gszBlockModelTrampolineLow;
gszBlockModels[BM_TRAMPOLINE_MID] = gszBlockModelTrampolineMid;
gszBlockModels[BM_TRAMPOLINE_HIGH] = gszBlockModelTrampolineHigh;
gszBlockModels[BM_LIGHT] = gszBlockModelLight;
gszBlockModels[BM_NOFALLDAMAGEBHOP] = gszBlockModelNoFallDamageBhop;
gszBlockModels[BM_DUCK] = gszBlockModelDuck;
gszBlockModels[BM_MONEY] = gszBlockModelMoney;
gszBlockModels[BM_SUPERMAN] = gszBlockModelSuperman;
gszBlockModels[BM_XP] = gszBlockModelXP;
gszBlockModels[BM_SHOTGUN] = gszBlockModelShotgun;
gszBlockModels[BM_SCOUT] = gszBlockModelScout;
gszBlockModels[BM_AK47] = gszBlockModelAk47;
gszBlockModels[BM_M4A1] = gszBlockModelM4a1;
gszBlockModels[BM_USP] = gszBlockModelUsp;
gszBlockModels[BM_FAMAS] = gszBlockModelFamas;
gszBlockModels[BM_GLOCK] = gszBlockModelGlock;
gszBlockModels[BM_P90] = gszBlockModelP90;
gszBlockModels[BM_GALIL] = gszBlockModelGalil;
//setup default block rendering (unlisted block use normal rendering)
setupBlockRendering(BM_INVINCIBILITY, GLOWSHELL, 55, 55, 55, 16);
setupBlockRendering(BM_STEALTH, TRANSWHITE, 255, 255, 255, 50);
setupBlockRendering(BM_GLASS, TRANSWHITE, 255, 255, 255, 100);
setupBlockRendering(BM_GLASS_IGZ, TRANSWHITE, 255, 255, 255, 100);
setupBlockRendering(BM_GLASS_NORMAL, TRANSALPHA, 255, 255, 255, 175);
//process block models config file
processBlockModels();
new szBlockModelSmall[256];
new szBlockModelLarge[256];
new szBlockModelPole[256];
//precache blocks
for (new i = 0; i < gBlockMax; ++i)
{
//get filenames for the small and large blocks based on normal block name
setBlockModelNameSmall(szBlockModelSmall, gszBlockModels[i], 256);
setBlockModelNameLarge(szBlockModelLarge, gszBlockModels[i], 256);
setBlockModelNamePole(szBlockModelPole, gszBlockModels[i], 256);
precache_model(gszBlockModels[i]);
precache_model(szBlockModelSmall);
precache_model(szBlockModelLarge);
precache_model(szBlockModelPole);
}
//precache sounds
precache_sound(gszTeleportSound);
precache_sound(gszInvincibleSound);
precache_sound(gszCamouflageSound);
precache_sound(gszStealthSound);
precache_sound(gszFireSoundFlame);
precache_sound(gszBootsOfSpeedSound);
precache_model(gszTeleportSpriteStart);
precache_model(gszTeleportSpriteEnd);
}
public plugin_cfg()
{
//format help text filename
format(gszHelpFilename, 32, gszHelpFilenameFormat, VERSION);
//create help title
format(gszHelpTitle, sizeof(gszHelpTitle), "%s v%s by %s", PLUGIN, VERSION, AUTHOR);
//read in help text from file
new szConfigsDir[32];
new szHelpFilename[64];
new szLine[128];
get_configsdir(szConfigsDir, 32);
format(szHelpFilename, sizeof(szHelpFilename), "%s/%s", szConfigsDir, gszHelpFilename);
//open help file for reading
new f = fopen(szHelpFilename, "rt");
//iterate through all the lines in the file
new size = sizeof(gszHelpText);
while (!feof(f))
{
fgets(f, szLine, 128);
add(gszHelpText, size, szLine);
}
//close file
fclose(f);
//get id for message 'ScreenFade'
gMsgScreenFade = get_user_msgid("ScreenFade");
//load blocks from file
loadBlocks(0);
}
createMenus()
{
//calculate maximum number of block menu pages from maximum amount of blocks
gBlockMenuPagesMax = floatround((float(gBlockMax) / 8.0), floatround_ceil);
//create main menu
new size = sizeof(gszMainMenu);
add(gszMainMenu, size, "\y[staNioN-MM] BlockMaker MainMenu^n^n");
add(gszMainMenu, size, "\r1. \wBlock Menu^n");
add(gszMainMenu, size, "\r2. \wTeleport Menu^n^n^n^n");
add(gszMainMenu, size, "\r6. %s\wNoclip: %s^n");
add(gszMainMenu, size, "\r7. %s\wGodmode: %s^n^n");
add(gszMainMenu, size, "\r9. \wOptions Menu^n");
add(gszMainMenu, size, "\r0. \wClose");
gKeysMainMenu = B1 | B2 | B6 | B7 | B9 | B0;
//create block menu
size = sizeof(gszBlockMenu);
add(gszBlockMenu, size, "\y[staNioN-MM] BlockMenu^n^n");
add(gszBlockMenu, size, "\r1. \wBlock Type: \y%s^n");
add(gszBlockMenu, size, "\r2. %s\wCreate Block^n");
add(gszBlockMenu, size, "\r3. %s\wConvert Block^n");
add(gszBlockMenu, size, "\r4. %s\wDelete Block^n");
add(gszBlockMenu, size, "\r5. %s\wRotate Block^n^n");
add(gszBlockMenu, size, "\r6. %s\wNoclip: %s^n");
add(gszBlockMenu, size, "\r7. %s\wGodmode: %s^n");
add(gszBlockMenu, size, "\r8. \wBlock Size: \y%s^n^n");
add(gszBlockMenu, size, "\r9. \wOptions Menu^n");
add(gszBlockMenu, size, "\r0. \yBack");
gKeysBlockMenu = B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B0;
gKeysBlockSelectionMenu = B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B0;
//create teleport menu
size = sizeof(gszTeleportMenu);
add(gszTeleportMenu, size, "\y[staNioN-MM] Teleport Menu^n^n");
add(gszTeleportMenu, size, "\r1. %s\wTeleport Start^n");
add(gszTeleportMenu, size, "\r2. %s\wTeleport Destination^n");
add(gszTeleportMenu, size, "\r3. %s\wSwap Teleport Start/Destination^n");
add(gszTeleportMenu, size, "\r4. %s\wDelete Teleport^n");
add(gszTeleportMenu, size, "\r5. %s\wTeleport Path^n^n");
add(gszTeleportMenu, size, "\r6. %s\wNoclip: %s^n");
add(gszTeleportMenu, size, "\r7. %s\wGodmode: %s^n^n^n");
add(gszTeleportMenu, size, "\r9. \wOptions^n");
add(gszTeleportMenu, size, "\r0. \yBack");
gKeysTeleportMenu = B1 | B2 | B3 | B4 | B5 | B6 | B7 | B9 | B0;
//create the options menu
size = sizeof(gszOptionsMenu);
add(gszOptionsMenu, size, "\y[staNioN-MM] Options Menu^n^n");
add(gszOptionsMenu, size, "\r1. %s\wSnapping: %s^n");
add(gszOptionsMenu, size, "\r2. %s\wSnapping gap: \r%.1f^n^n");
add(gszOptionsMenu, size, "\r3. %s\wAdd to group^n");
add(gszOptionsMenu, size, "\r4. %s\wClear group^n^n");
add(gszOptionsMenu, size, "\r5. %s\wDelete all blocks^n");
add(gszOptionsMenu, size, "\r6. %s\wDelete all teleports^n^n");
add(gszOptionsMenu, size, "\r7. %s\wSave to file^n");
add(gszOptionsMenu, size, "\r8. %s\wLoad from file^n^n");
add(gszOptionsMenu, size, "\r9. \wHelp^n");
add(gszOptionsMenu, size, "\r0. \yBack");
gKeysOptionsMenu = B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B0;
//create choice (YES/NO) menu
size = sizeof(gszChoiceMenu);
add(gszChoiceMenu, size, "\w%s^n^n");
add(gszChoiceMenu, size, "\r1. \wYes^n");
add(gszChoiceMenu, size, "\r2. \wNo^n^n^n^n^n^n^n^n^n^n");
add(gszChoiceMenu, size, "\r0. \yBack");
gKeysChoiceMenu = B1 | B2 | B0;
}
setupBlockRendering(blockType, renderType, red, green, blue, alpha)
{
gRender[blockType] = renderType;
gRed[blockType] = red;
gGreen[blockType] = green;
gBlue[blockType] = blue;
gAlpha[blockType] = alpha;
}
setBlockModelNameLarge(szBlockModelTarget[256], szBlockModelSource[256], size)
{
szBlockModelTarget = szBlockModelSource;
replace(szBlockModelTarget, size, ".mdl", "_large.mdl");
}
setBlockModelNameSmall(szBlockModelTarget[256], szBlockModelSource[256], size)
{
szBlockModelTarget = szBlockModelSource;
replace(szBlockModelTarget, size, ".mdl", "_small.mdl");
}
setBlockModelNamePole(szBlockModelTarget[256], szBlockModelSource[256], size)
{
szBlockModelTarget = szBlockModelSource;
replace(szBlockModelTarget, size, ".mdl", "_pole.mdl");
}
processBlockModels()
{
//get full path to block models config file
new szBlockModelsFile[96];
get_configsdir(szBlockModelsFile, 96);
add(szBlockModelsFile, 96, "/blockmaker_models.ini");
//open block models config file for reading
new f = fopen(szBlockModelsFile, "rt");
new szData[160];
new szType[32];
new szBlockModel[256];
new szRender[16];
new szRed[8];
new szGreen[8];
new szBlue[8];
new szAlpha[8];
new blockType;
new render;
new red;
new green;
new blue;
new alpha;
//iterate through all the lines in the file
while (!feof(f))
{
//clear data
szBlockModel = "";
szRender = "";
szRed = "";
szGreen = "";
szBlue = "";
szAlpha = "";
blockType = -1;
//get and parse a line of data from file
fgets(f, szData, 160);
parse(szData, szType, 24, szBlockModel, 64, szRender, 16, szRed, 8, szGreen, 8, szBlue, 8, szAlpha, 8);
//replace '\' with '/' in block model path
replace_all(szBlockModel, 64, "\", "/");
if (equal(szType, "PLATFORM")) blockType = BM_PLATFORM;
else if (equal(szType, "BHOP")) blockType = BM_BHOP;
else if (equal(szType, "DAMAGE")) blockType = BM_DAMAGE;
else if (equal(szType, "HEALER")) blockType = BM_HEALER;
else if (equal(szType, "NOFALLDAMAGE")) blockType = BM_NOFALLDAMAGE;
else if (equal(szType, "ICE")) blockType = BM_ICE;
else if (equal(szType, "SPEEDBOOST")) blockType = BM_SPEEDBOOST;
else if (equal(szType, "INVINCIBILITY")) blockType = BM_INVINCIBILITY;
else if (equal(szType, "STEALTH")) blockType = BM_STEALTH;
else if (equal(szType, "DEATH")) blockType = BM_DEATH;
else if (equal(szType, "CAMOUFLAGE")) blockType = BM_CAMOUFLAGE;
else if (equal(szType, "LOWGRAVITY")) blockType = BM_LOWGRAVITY;
else if (equal(szType, "FIRE")) blockType = BM_FIRE;
else if (equal(szType, "SLAP")) blockType = BM_SLAP;
else if (equal(szType, "RANDOM")) blockType = BM_RANDOM;
else if (equal(szType, "HONEY")) blockType = BM_HONEY;
else if (equal(szType, "BARRIER_CT")) blockType = BM_BARRIER_CT;
else if (equal(szType, "BARRIER_T")) blockType = BM_BARRIER_T;
else if (equal(szType, "BOOTSOFSPEED")) blockType = BM_BOOTSOFSPEED;
else if (equal(szType, "GLASS")) blockType = BM_GLASS;
else if (equal(szType, "GLASS_igz")) blockType = BM_GLASS_IGZ;
else if (equal(szType, "GLASS_Normal")) blockType = BM_GLASS_NORMAL;
else if (equal(szType, "BHOP_NOSLOW")) blockType = BM_BHOP_NOSLOW;
else if (equal(szType, "DELAYED_BHOP")) blockType = BM_DELAYEDBHOP;
else if (equal(szType, "FADE")) blockType = BM_FADE;
else if (equal(szType, "DEAGLE")) blockType = BM_DEAGLE;
else if (equal(szType, "HE")) blockType = BM_HE;
else if (equal(szType, "SMOKE")) blockType = BM_SMOKE;
else if (equal(szType, "FLASH")) blockType = BM_FLASH;
else if (equal(szType, "AWP")) blockType = BM_AWP;
else if (equal(szType, "TRAMPOLINE_LOW")) blockType = BM_TRAMPOLINE_LOW;
else if (equal(szType, "TRAMPOLINE_MID")) blockType = BM_TRAMPOLINE_MID;
else if (equal(szType, "TRAMPOLINE_HIGH")) blockType = BM_TRAMPOLINE_HIGH;
else if (equal(szType, "LIGHT")) blockType = BM_LIGHT;
else if (equal(szType, "NOFALLDAMAGEBHOP")) blockType = BM_NOFALLDAMAGEBHOP;
else if (equal(szType, "DUCK")) blockType = BM_DUCK;
else if (equal(szType, "MONEY")) blockType = BM_MONEY;
else if (equal(szType, "SUPERMAN")) blockType = BM_SUPERMAN;
else if (equal(szType, "XP")) blockType = BM_XP;
else if (equal(szType, "Shotgun")) blockType = BM_SHOTGUN;
else if (equal(szType, "Scout")) blockType = BM_SCOUT;
else if (equal(szType, "Ak47")) blockType = BM_AK47;
else if (equal(szType, "M4a1")) blockType = BM_M4A1;
else if (equal(szType, "Usp")) blockType = BM_USP;
else if (equal(szType, "Famas")) blockType = BM_FAMAS;
else if (equal(szType, "Glock")) blockType = BM_GLOCK;
else if (equal(szType, "P90")) blockType = BM_P90;
else if (equal(szType, "Galil")) blockType = BM_GALIL;
//if we're dealing with a valid block type
if (blockType >= 0 && blockType < gBlockMax)
{
new bool:bDoRendering = false;
//if block model file exists
if (file_exists(szBlockModel))
{
//set block models for given block type
gszBlockModels[blockType] = szBlockModel;
//block model file does exist so process rendering values as well
bDoRendering = true;
}
else
{
if (equal(szBlockModel, "DEFAULT"))
{
//block is set to use default so process rendering values
bDoRendering = true;
}
}
//process rendering values
if (bDoRendering)
{
render = NORMAL;
red = 255;
green = 255;
blue = 255;
alpha = 255;
if (equal(szRender, "GLOWSHELL")) render = GLOWSHELL;
if (equal(szRender, "TRANSCOLOR")) render = TRANSCOLOR;
if (equal(szRender, "TRANSALPHA")) render = TRANSALPHA;
if (equal(szRender, "TRANSWHITE")) render = TRANSWHITE;
if (strlen(szRed) > 0) red = str_to_num(szRed);
if (strlen(szGreen) > 0) green = str_to_num(szGreen);
if (strlen(szBlue) > 0) blue = str_to_num(szBlue);
if (strlen(szAlpha) > 0) alpha = str_to_num(szAlpha);
//set blocks rendering values
setupBlockRendering(blockType, render, red, green, blue, alpha);
}
}
}
//close file
fclose(f);
}
/***** FORWARDS *****/
public client_connect(id)
{
//make sure snapping is on by default
gbSnapping[id] = true;
//players chosen snapping gap defaults to 0.0 units
gfSnappingGap[id] = 0.0;
//make sure players can die
gbNoFallDamage[id] = false;
//make sure players can die
gbNoFallDamageBhop[id] = false;
//players block selection menu is on page 1
gBlockMenuPage[id] = 1;
//player doesn't have godmode or noclip
gbAdminGodmode[id] = false;
gbAdminNoclip[id] = false;
//player doesn't have any blocks grouped
gGroupCount[id] = 0;
}
public client_disconnect(id)
{
//clear players group
groupClear(id);
//if player was grabbing an entity when they disconnected
if (gGrabbed[id])
{
//if entity is valid
if (is_valid_ent(gGrabbed[id]))
{
//set the entity to 'not being grabbed'
entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
}
gGrabbed[id] = 0;
}
}
public pfn_touch(ent, id)
{
//if touch event involves a player
if (id > 0 && id <= 32)
{
//if player is alive
if (is_user_alive(id))
{
//if entity involved is a block
if (isBlock(ent))
{
//get the blocktype
new blockType = entity_get_int(ent, EV_INT_body);
//if blocktype is a bunnyhop block or barrier
if (blockType == BM_BHOP || blockType == BM_BARRIER_CT || blockType == BM_BARRIER_T || blockType == BM_BHOP_NOSLOW || blockType == BM_DELAYEDBHOP || blockType == BM_NOFALLDAMAGEBHOP)
{
//if task does not already exist for bunnyhop block
if (!task_exists(TASK_BHOPSOLIDNOT + ent) && !task_exists(TASK_BHOPSOLID + ent))
{
//get the players team
new CsTeams:team = cs_get_user_team(id);
//if players team is different to barrier
if (blockType == BM_BARRIER_CT && team == CS_TEAM_T)
{
//make block SOLID_NOT without any delay
taskSolidNot(TASK_BHOPSOLIDNOT + ent);
}
else if (blockType == BM_BARRIER_T && team == CS_TEAM_CT)
{
//make block SOLID_NOT without any delay
taskSolidNot(TASK_BHOPSOLIDNOT + ent);
}
else if (blockType == BM_BHOP || blockType == BM_BHOP_NOSLOW || blockType == BM_NOFALLDAMAGEBHOP)
{
if(IsUnderAttack(id, ent))
{
return;
}
//set bhop block to be SOLID_NOT after 0.1 seconds
set_task(0.1, "taskSolidNot", TASK_BHOPSOLIDNOT + ent);
}
else if (blockType == BM_DELAYEDBHOP)
{
if(IsUnderAttack(id, ent))
{
return;
}
set_task(2.0, "taskSolidNot", TASK_BHOPSOLIDNOT + ent);
}
}
}
}
}
}
return;
}
IsUnderAttack(id, iEnt)
{
static iTr;
iTr = create_tr2();
static Float:vOrigin[3], Float:vEnd[3];
pev(id, pev_origin, vOrigin);
vEnd[0] = vOrigin[0];
vEnd[1] = vOrigin[1];
vEnd[2] = vOrigin[2] + ( 50 );
static iHitEnt;
engfunc(EngFunc_TraceLine, vOrigin, vEnd, DONT_IGNORE_MONSTERS, id, iTr);
iHitEnt = get_tr2(iTr, TR_pHit);
free_tr2(iTr);
if(iEnt == iHitEnt)
{
static szName[32]; get_user_name(id, szName, 31);
ColorChat(id, TEAM_COLOR, "^4%s ^4%s ^3Tried to ^4underblock!", gszPrefix, szName);
return 1;
}
return 0;
}
public server_frame()
{
new ent;
new Float:vOrigin[3];
new bool:entNear = false;
new tele;
new entinsphere;
//iterate through all players and remove slow down after jumping
for (new i = 1; i <= 32; ++i)
{
if (is_user_alive(i))
{
if (gbOnIce[i] || gbNoSlowDown[i])
{
entity_set_float(i, EV_FL_fuser2, 0.0);
}
}
}
//find all teleport start entities in map and if a player is close to one, teleport the player
while ((ent = find_ent_by_class(ent, gszTeleportStartClassname)))
{
new Float:vOrigin[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin);
//teleport players and grenades within a sphere around the teleport start entity
entinsphere = -1;
while ((entinsphere = find_ent_in_sphere(entinsphere, vOrigin, 32.0)))
{
//get classname of entity
new szClassname[32];
entity_get_string(entinsphere, EV_SZ_classname, szClassname, 32);
//if entity is a player
if (entinsphere > 0 && entinsphere <= 32)
{
//only teleport player if they're alive
if (is_user_alive(entinsphere))
{
//teleport the player
actionTeleport(entinsphere, ent);
}
}
//or if entity is a grenade
else if (equal(szClassname, "grenade"))
{
//get the end of the teleport
tele = entity_get_int(ent, EV_INT_iuser1);
//if the end of the teleport exists
if (tele)
{
//set the end of the teleport to be not solid
entity_set_int(tele, EV_INT_solid, SOLID_NOT); //can't be grabbed or deleted
//teleport the grenade
actionTeleport(entinsphere, ent);
//set a time in the teleport it will become solid after 2 seconds
entity_set_float(tele, EV_FL_ltime, halflife_time() + 2.0);
}
}
}
}
//make teleporters SOLID_NOT when players are near them
while ((ent = find_ent_by_class(ent, gszTeleportEndClassname)))
{
//get the origin of the teleport end entity
entity_get_vector(ent, EV_VEC_origin, vOrigin);
//compare this origin with all player and grenade origins
entinsphere = -1;
while ((entinsphere = find_ent_in_sphere(entinsphere, vOrigin, 64.0)))
{
//get classname of entity
new szClassname[32];
entity_get_string(entinsphere, EV_SZ_classname, szClassname, 32);
//if entity is a player
if (entinsphere > 0 && entinsphere <= 32)
{
//make sure player is alive
if (is_user_alive(entinsphere))
{
entNear = true;
break;
}
}
//or if entity is a grenade
else if (equal(szClassname, "grenade"))
{
entNear = true;
break;
}
}
//set the solid type of the teleport end entity depending on whether or not a player is near
if (entNear)
{
//only do this if it is not being grabbed
if (entity_get_int(ent, EV_INT_iuser2) == 0)
{
entity_set_int(ent, EV_INT_solid, SOLID_NOT); //can't be grabbed or deleted
}
}
else
{
//get time from teleport end entity to check if it can go solid
new Float:fTime = entity_get_float(ent, EV_FL_ltime);
//only set teleport end entity to solid if its 'solid not' time has elapsed
if (halflife_time() >= fTime)
{
entity_set_int(ent, EV_INT_solid, SOLID_BBOX); //CAN be grabbed and deleted
}
}
}
//find all block entities
while ((ent = find_ent_by_class(ent, gszBlockClassname)))
{
//get block type
new blockType = entity_get_int(ent, EV_INT_body);
//if block is a speed boost
if (blockType == BM_SPEEDBOOST)
{
new Float:vOrigin[3];
new Float:pOrigin[3];
new Float:dist = 9999.9;
new Float:playerDist = 9999.9;
new nearestPlayer = 0;
//get the origin of the speed boost block
entity_get_vector(ent, EV_VEC_origin, vOrigin);
//compare this origin with all players origins to find the nearest player to the block
for (new id = 1; id <= 32; ++id)
{
//if player is alive
if (is_user_alive(id))
{
//get player origin
entity_get_vector(id, EV_VEC_origin, pOrigin);
//get the distance from the block to the player
dist = get_distance_f(vOrigin, pOrigin);
if (dist < playerDist)
{
nearestPlayer = id;
playerDist = dist;
}
}
}
//if we found a player within 100 units of the speed boost block
if (nearestPlayer > 0 && playerDist < 200.0)
{
//get the sprite on top of the speed boost block
new sprite = entity_get_int(ent, EV_INT_iuser3);
//make sure sprite entity is valid
if (sprite)
{
new Float:vAngles[3];
//get the direction the player is looking
entity_get_vector(nearestPlayer, EV_VEC_angles, vAngles);
//set the angles of the sprite to be the same as the player
vAngles[0] = 90.0; //always make sure sprite is flat to the block
vAngles[1] += 90.0; //rotate the sprite by 90 because it doesnt point up (PAT!)
entity_set_vector(sprite, EV_VEC_angles, vAngles);
}
}
}
}
}
public client_PreThink(id)
{
//make sure player is connected
if (is_user_connected(id))
{
//display type of block that player is aiming at
new ent, body;
get_user_aiming(id, ent, body, 555);
if (isBlock(ent) && (pev(id, pev_button) & IN_USE && !(pev(id, pev_oldbuttons) & IN_USE) ))
{
new blockType = entity_get_int(ent, EV_INT_body);
new szCreator[32];
pev(ent, pev_targetname, szCreator, 31);
replace_all(szCreator, 31, "_", " ");
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "[staNioN-MM]^n Block Type: %s^nCreator: %s", gszBlockNames[blockType], szCreator);
}
//make sure player is alive
if (is_user_alive(id))
{
//if player has low gravity
if (gbLowGravity[id])
{
//get players flags
new flags = entity_get_int(id, EV_INT_flags);
//if player has feet on the ground, set gravity to normal
if (flags & FL_ONGROUND)
{
set_user_gravity(id);
gbLowGravity[id] = false;
}
}
//trace directly down to see if there is a block beneath player
new Float:pOrigin[3];
new Float:pSize[3];
new Float:pMaxs[3];
new Float:vTrace[3];
new Float:vReturn[3];
entity_get_vector(id, EV_VEC_origin, pOrigin);
entity_get_vector(id, EV_VEC_size, pSize);
entity_get_vector(id, EV_VEC_maxs, pMaxs);
//calculate position of players feet
pOrigin[2] = pOrigin[2] - ((pSize[2] - 36.0) - (pMaxs[2] - 36.0));
//make the trace small for some blocks
vTrace[2] = pOrigin[2] - 1.0;
//do 4 traces for each corner of the player
for (new i = 0; i < 4; ++i)
{
switch (i)
{
case 0: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] + 16; }
case 1: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] + 16; }
case 2: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] - 16; }
case 3: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] - 16; }
}
ent = trace_line(id, pOrigin, vTrace, vReturn);
//if entity found is a block
if (isBlock(ent))
{
new blockType = entity_get_int(ent, EV_INT_body);
switch (blockType)
{
case BM_HEALER: actionHeal(id);
case BM_DAMAGE: actionDamage(id);
case BM_INVINCIBILITY: actionInvincible(id, false);
case BM_STEALTH: actionStealth(id, false);
case BM_SPEEDBOOST: actionSpeedBoost(id);
case BM_DEATH: actionDeath(id);
case BM_LOWGRAVITY: actionLowGravity(id);
case BM_CAMOUFLAGE: actionCamouflage(id, false);
case BM_FIRE: actionFire(id, ent);
case BM_SLAP: actionSlap(id);
case BM_RANDOM: actionRandom(id, ent);
case BM_HONEY: actionHoney(id);
case BM_BOOTSOFSPEED: actionBootsOfSpeed(id, false);
case BM_FADE: actionFade(id);
case BM_DEAGLE: actionDEagle(id);
case BM_HE: actionGrenade(id, HE);
case BM_SMOKE: actionGrenade(id, SMOKE);
case BM_FLASH: actionGrenade(id, FLASH);
case BM_AWP: actionAWP(id);
case BM_TRAMPOLINE_LOW: actionTrampolineLow(id);
case BM_TRAMPOLINE_MID: actionTrampolineMid(id);
case BM_TRAMPOLINE_HIGH: actionTrampolineHigh(id);
case BM_LIGHT: actionLight(id);
case BM_DUCK: actionDuck(id);
case BM_MONEY: actionMoney(id, false);
case BM_SUPERMAN: actionSuperman(id, false);
case BM_XP: actionXP(id, false);
case BM_SHOTGUN: actionShotgun(id);
case BM_SCOUT: actionScout(id);
case BM_AK47: actionAk47(id);
case BM_M4A1: actionM4a1(id);
case BM_USP: actionUsp(id);
case BM_FAMAS: actionFamas(id);
case BM_GLOCK: actionGlock(id);
case BM_P90: actionP90(id);
case BM_GALIL: actionGalil(id);
}
}
}
//make the trace longer for other blocks
vTrace[2] = pOrigin[2] - 20.0;
//do 4 traces for each corner of the player
for (new i = 0; i < 4; ++i)
{
switch (i)
{
case 0: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] + 16; }
case 1: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] + 16; }
case 2: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] - 16; }
case 3: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] - 16; }
}
ent = trace_line(id, pOrigin, vTrace, vReturn);
//if entity found is a block
if (isBlock(ent))
{
new blockType = entity_get_int(ent, EV_INT_body);
switch (blockType)
{
case BM_TRAMPOLINE_MID: actionTrampolineMid(id);
case BM_NOFALLDAMAGE: actionNoFallDamage(id);
case BM_ICE: actionOnIce(id);
case BM_BHOP_NOSLOW: actionNoSlowDown(id);
case BM_TRAMPOLINE_LOW: actionTrampolineLow(id);
case BM_TRAMPOLINE_HIGH: actionTrampolineHigh(id);
case BM_NOFALLDAMAGEBHOP: actionNoFallDamageBhop(id);
}
}
}
//display amount of invincibility/stealth/camouflage/boots of speed timeleft
new Float:fTime = halflife_time();
new Float:fTimeleftInvincible = gfInvincibleTimeOut[id] - fTime;
new Float:fTimeleftStealth = gfStealthTimeOut[id] - fTime;
new Float:fTimeleftCamouflage = gfCamouflageTimeOut[id] - fTime;
new Float:fTimeleftBootsOfSpeed = gfBootsOfSpeedTimeOut[id] - fTime;
new szTextToShow[256] = "";
new szText[48];
new bool:bShowText = false;
if (fTimeleftInvincible >= 0.0)
{
format(szText, sizeof(szText), "Invincible: %.1f^n", fTimeleftInvincible);
add(szTextToShow, sizeof(szTextToShow), szText);
bShowText = true;
}
if (fTimeleftStealth >= 0.0)
{
format(szText, sizeof(szText), "Stealth: %.1f^n", fTimeleftStealth);
add(szTextToShow, sizeof(szTextToShow), szText);
bShowText = true;
}
if (fTimeleftCamouflage >= 0.0)
{
//if player is a CT
if (get_user_team(id) == 1)
{
format(szText, sizeof(szText), "You look like a Counter-Terrorist: %.1f^n", fTimeleftCamouflage);
}
else
{
format(szText, sizeof(szText), "You look like a Terrorist: %.1f^n", fTimeleftCamouflage);
}
add(szTextToShow, sizeof(szTextToShow), szText);
bShowText = true;
}
if (fTimeleftBootsOfSpeed >= 0.0)
{
format(szText, sizeof(szText), "Boots of speed: %.1f^n", fTimeleftBootsOfSpeed);
add(szTextToShow, sizeof(szTextToShow), szText);
bShowText = true;
}
//if there is some text to show then show it
if (bShowText)
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, szTextToShow);
}
}
//get players buttons
new buttons = get_user_button(id);
new oldbuttons = get_user_oldbutton(id);
//if player has grabbed an entity
if (gGrabbed[id] > 0)
{
//check for a single press on the following buttons
if (buttons & IN_JUMP && !(oldbuttons & IN_JUMP)) cmdJump(id);
if (buttons & IN_DUCK && !(oldbuttons & IN_DUCK)) cmdDuck(id);
if (buttons & IN_ATTACK && !(oldbuttons & IN_ATTACK)) cmdAttack(id);
if (buttons & IN_ATTACK2 && !(oldbuttons & IN_ATTACK2)) cmdAttack2(id);
//prevent player from using attack
buttons &= ~IN_ATTACK;
entity_set_int(id, EV_INT_button, buttons);
//if player has grabbed a valid entity
if (is_valid_ent(gGrabbed[id]))
{
//if block the player is grabbing is in their group and group count is larger than 1
if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
{
new Float:vMoveTo[3];
new Float:vOffset[3];
new Float:vOrigin[3];
new block;
//move the block the player has grabbed and get the move vector
moveGrabbedEntity(id, vMoveTo);
//move the rest of the blocks in the players group using vector for grabbed block
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is still in this players group
if (isBlockInGroup(id, block))
{
//get offset vector from block
entity_get_vector(block, EV_VEC_vuser1, vOffset);
vOrigin[0] = vMoveTo[0] - vOffset[0];
vOrigin[1] = vMoveTo[1] - vOffset[1];
vOrigin[2] = vMoveTo[2] - vOffset[2];
//move grouped block
moveEntity(id, block, vOrigin, false);
}
}
}
else
{
//move the entity the player has grabbed
moveGrabbedEntity(id);
}
}
else
{
cmdRelease(id);
}
}
//if player has just deleted something
if (gbJustDeleted[id])
{
//if player is pressing attack2
if (buttons & IN_ATTACK2)
{
//prevent player from using attack2
buttons &= ~IN_ATTACK2;
entity_set_int(id, EV_INT_button, buttons);
}
else
{
//player has now NOT just deleted something
gbJustDeleted[id] = false;
}
}
}
return PLUGIN_CONTINUE;
}
public client_PostThink(id)
{
//if player is alive
if (is_user_alive(id))
{
//if player is set to not get fall damage
if (gbNoFallDamage[id])
{
entity_set_int(id, EV_INT_watertype, -3);
gbNoFallDamage[id] = false;
}
//if player is set to not get fall damage
if (gbNoFallDamageBhop[id])
{
entity_set_int(id, EV_INT_watertype, -3);
gbNoFallDamageBhop[id] = false;
}
}
}
/***** EVENTS *****/
public eventPlayerDeath()
{
new id = read_data(2);
resetTimers(id);
}
public eventRoundRestart()
{
//iterate through all players
for (new id = 1; id <= 32; ++id)
{
//reset all players timers
resetTimers(id);
grenade_taken[HE][id] = false;
grenade_taken[SMOKE][id] = false;
grenade_taken[FLASH][id] = false;
DEagleUsed[id] = false;
ShotgunUsed[id] = false;
ScoutUsed[id] = false;
AwpUsed[id] = false;
HeUsed[id] = false;
FrostUsed[id] = false;
FlashUsed[id] = false;
Ak47Used[id] = false;
M4a1Used[id] = false;
UspUsed[id] = false;
FamasUsed[id] = false;
GlockUsed[id] = false;
P90Used[id] = false;
GalilUsed[id] = false;
}
}
public eventPlayerSpawn(id)
{
//if player has godmode enabled
if (gbAdminGodmode[id])
{
//re-enable godmode on player
set_user_godmode(id, 1);
}
//if player has noclip enabled
if (gbAdminNoclip[id])
{
//re-enable noclip on player
set_user_noclip(id, 1);
}
}
resetTimers(id)
{
gfInvincibleTimeOut[id] = 0.0;
gfInvincibleNextUse[id] = 0.0;
gfStealthTimeOut[id] = 0.0;
gfStealthNextUse[id] = 0.0;
gfCamouflageTimeOut[id] = 0.0;
gfCamouflageNextUse[id] = 0.0;
gbOnFire[id] = false;
gfRandomNextUse[id] = 0.0;
gfBootsOfSpeedTimeOut[id] = 0.0;
gfBootsOfSpeedNextUse[id] = 0.0;
gfMoneyNextUse[id] = 0.0;
gfSupermanTimeOut[id] = 0.0;
gfSupermanNextUse[id] = 0.0;
gfXPNextUse[id] = 0.0;
//remove any task this player might have
new taskId = TASK_INVINCIBLE + id;
if (task_exists(taskId))
{
remove_task(taskId);
}
taskId = TASK_STEALTH + id;
if (task_exists(taskId))
{
remove_task(taskId);
}
taskId = TASK_CAMOUFLAGE + id;
if (task_exists(taskId))
{
remove_task(taskId);
//change back to players old model
cs_set_user_model(id, gszCamouflageOldModel[id]);
}
taskId = TASK_BOOTSOFSPEED + id;
if (task_exists(taskId))
{
remove_task(taskId);
}
//make sure player is connected
if (is_user_connected(id))
{
//set players rendering to normal
set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 255);
}
//player is not 'on ice'
gbOnIce[id] = false;
//player slows down after jumping
gbNoSlowDown[id] = false;
}
public eventCurWeapon(id)
{
new Float:fTime = halflife_time();
new Float:fTimeleftBootsOfSpeed = gfBootsOfSpeedTimeOut[id] - fTime;
//if the player has the boots of speed
if (fTimeleftBootsOfSpeed >= 0.0)
{
//set their max speed so they obtain their speed after changing weapon
set_user_maxspeed(id, gfBootsMaxSpeed);
}
}
/***** BLOCK ACTIONS *****/
actionXP(id, OverrideTimer)
{
new Float:fTime = halflife_time();
if (fTime >= gfXPNextUse[id] || OverrideTimer)
{
if ( get_user_team ( id ) == 1 )
{
hnsxp_add_user_xp(id, 100);
ColorChat(id, TEAM_COLOR, "^3You have been given ^4100 ^3XP!");
}
gfXPNextUse[id] = fTime + get_cvar_float("bm_xpcooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Wait Time: One Round", gfXPNextUse[id] - fTime);
}
return PLUGIN_HANDLED;
}
actionSuperman(id, OverrideTimer)
{
new Float:fTime = halflife_time();
if (fTime >= gfSupermanNextUse[id] || OverrideTimer)
{
new Float:fTimeout = get_cvar_float("bm_supermantime");
set_task(fTimeout, "taskSupermanRemove", TASK_SUPERMAN + id, "", 0, "a", 1);
set_user_gravity(id, 0.50);
gfSupermanTimeOut[id] = fTime + fTimeout;
gfSupermanNextUse[id] = fTime + fTimeout + get_cvar_float("bm_supermancooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Superman next use: %.1f", gfSupermanNextUse[id] - fTime);
}
}
actionMoney(id, OverrideTimer)
{
new Float:fTime = halflife_time();
if (fTime >= gfMoneyNextUse[id] || OverrideTimer)
{
if ( get_user_team ( id ) == 1 )
{
if ( cs_get_user_money( id ) == 16000 )
{
return PLUGIN_HANDLED;
}
else
{
cs_set_user_money(id, cs_get_user_money(id) + 5000);
}
}
gfMoneyNextUse[id] = fTime + get_cvar_float("bm_moneycooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Wait Time: One Round", gfMoneyNextUse[id] - fTime);
}
return PLUGIN_HANDLED;
}
actionDuck(id)
{
entity_set_int(id, EV_INT_bInDuck, 15);
}
actionLight(id)
{
new origin[3];
get_user_origin(id, origin);
message_begin(MSG_BROADCAST,SVC_TEMPENTITY,origin);
if ( get_user_team ( id ) == 1 ) {
write_byte(TE_DLIGHT);
write_coord(origin[0]);
write_coord(origin[1]);
write_coord(origin[2]);
write_byte(50);
write_byte(255);
write_byte(0);
write_byte(0);
write_byte(255);
write_byte(50);
message_end();
}
if ( get_user_team ( id ) == 2 ) {
write_byte(TE_DLIGHT);
write_coord(origin[0]);
write_coord(origin[1]);
write_coord(origin[2]);
write_byte(50);
write_byte(0);
write_byte(0);
write_byte(255);
write_byte(255);
write_byte(50);
message_end();
}
if ( get_user_team ( id ) == 3 ) {
write_byte(TE_DLIGHT);
write_coord(origin[0]);
write_coord(origin[1]);
write_coord(origin[2]);
write_byte(50);
write_byte(69);
write_byte(69);
write_byte(69);
write_byte(255);
write_byte(50);
message_end();
}
}
actionDamage(id)
{
if (halflife_time() >= gfNextDamageTime[id])
{
if (get_user_health(id) > 0)
{
new Float:amount = get_cvar_float("bm_damageamount");
fakedamage(id, "damage block", amount, DMG_CRUSH);
}
gfNextDamageTime[id] = halflife_time() + 0.5;
}
}
actionHeal(id)
{
if (halflife_time() >= gfNextHealTime[id])
{
new hp = get_user_health(id);
new amount = floatround(get_cvar_float("bm_healamount"), floatround_floor);
new sum = (hp + amount);
if (sum < 100)
{
set_user_health(id, sum);
}
else if (hp > 101)
{
set_user_health( id, hp );
}
gfNextHealTime[id] = halflife_time() + 0.5;
}
}
actionInvincible(id, OverrideTimer)
{
new Float:fTime = halflife_time();
if (fTime >= gfInvincibleNextUse[id] || OverrideTimer)
{
new Float:fTimeout = get_cvar_float("bm_invincibletime");
set_user_godmode(id, 1);
set_task(fTimeout, "taskInvincibleRemove", TASK_INVINCIBLE + id, "", 0, "a", 1);
//only make player glow white for invincibility if player isn't already stealth
if (fTime >= gfStealthTimeOut[id])
{
set_user_rendering(id, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 16);
}
//play invincibility sound
emit_sound(id, CHAN_STATIC, gszInvincibleSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
gfInvincibleTimeOut[id] = fTime + fTimeout;
gfInvincibleNextUse[id] = fTime + fTimeout + get_cvar_float("bm_invinciblecooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Invincibility next use: %.1f", gfInvincibleNextUse[id] - fTime);
}
}
actionStealth(id, OverrideTimer)
{
new Float:fTime = halflife_time();
//check if player is outside of cooldown time to use stealth
if (fTime >= gfStealthNextUse[id] || OverrideTimer)
{
new Float:fTimeout = get_cvar_float("bm_stealthtime");
//set a task to remove stealth after time out amount
set_task(fTimeout, "taskStealthRemove", TASK_STEALTH + id, "", 0, "a", 1);
//make player invisible
set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderTransColor, 0);
//play stealth sound
emit_sound(id, CHAN_STATIC, gszStealthSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
gfStealthTimeOut[id] = fTime + fTimeout;
gfStealthNextUse[id] = fTime + fTimeout + get_cvar_float("bm_stealthcooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Stealth next use: %.1f", gfStealthNextUse[id] - fTime);
}
}
actionTrampolineMid(id)
{
//if trampoline timeout has exceeded (needed to prevent velocity being given multiple times)
if (halflife_time() >= gfTrampolineTimeout[id])
{
new Float:velocity[3];
//set player Z velocity to make player bounce
entity_get_vector(id, EV_VEC_velocity, velocity);
velocity[2] = 500.0; //jump velocity
entity_set_vector(id, EV_VEC_velocity, velocity);
entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
gfTrampolineTimeout[id] = halflife_time() + 0.5;
}
}
actionTrampolineLow(id)
{
//if trampoline timeout has exceeded (needed to prevent velocity being given multiple times)
if (halflife_time() >= gfTrampolineLowTimeout[id])
{
new Float:velocity[3];
//set player Z velocity to make player bounce
entity_get_vector(id, EV_VEC_velocity, velocity);
velocity[2] = 250.0; //jump velocity
entity_set_vector(id, EV_VEC_velocity, velocity);
entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
gfTrampolineLowTimeout[id] = halflife_time() + 0.5;
}
}
actionTrampolineHigh(id)
{
//if trampoline timeout has exceeded (needed to prevent velocity being given multiple times)
if (halflife_time() >= gfTrampolineMidTimeout[id])
{
new Float:velocity[3];
//set player Z velocity to make player bounce
entity_get_vector(id, EV_VEC_velocity, velocity);
velocity[2] = 750.0; //jump velocity
entity_set_vector(id, EV_VEC_velocity, velocity);
entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
gfTrampolineMidTimeout[id] = halflife_time() + 0.5;
}
}
actionSpeedBoost(id)
{
//if speed boost timeout has exceeded (needed to prevent speed boost being given multiple times)
if (halflife_time() >= gfSpeedBoostTimeOut[id])
{
new Float:pAim[3];
//set velocity on player in direction they're aiming
velocity_by_aim(id, 800, pAim);
pAim[2] = 260.0; //make sure Z velocity is only as high as a jump
entity_set_vector(id, EV_VEC_velocity, pAim);
entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
gfSpeedBoostTimeOut[id] = halflife_time() + 0.5;
}
}
actionNoFallDamage(id)
{
//set the player to not receive any fall damage (handled in client_PostThink)
gbNoFallDamage[id] = true;
}
actionNoFallDamageBhop(id)
{
//set the player to not receive any fall damage (handled in client_PostThink)
gbNoFallDamageBhop[id] = true;
}
actionOnIce(id)
{
new taskid = TASK_ICE + id;
if (!gbOnIce[id])
{
//save players maxspeed value
gfOldMaxSpeed[id] = get_user_maxspeed(id);
//make player feel like they're on ice
entity_set_float(id, EV_FL_friction, 0.15);
set_user_maxspeed(id, 600.0);
//player is now 'on ice'
gbOnIce[id] = true;
}
//remove any existing 'not on ice' task
if (task_exists(taskid))
{
remove_task(taskid);
}
//set task to remove 'on ice' effect very soon (task replaced if player is still on ice before task time reached)
set_task(0.1, "taskNotOnIce", taskid);
}
actionDeath(id)
{
//if player does not have godmode enabled (admin godmode or invincibility)
if (!get_user_godmode(id))
{
//kill player by inflicting massive damage
fakedamage(id, "the block of death", 10000.0, DMG_GENERIC);
new Deathname[42];
get_user_name(id, Deathname, 32);
set_hudmessage(255, 0, 0, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "%s Died on a Death", Deathname);
}
}
actionCamouflage(id, OverrideTimer)
{
new Float:fTime = halflife_time();
//check if player is outside of cooldown time to use camouflage
if (fTime >= gfCamouflageNextUse[id] || OverrideTimer)
{
new Float:fTimeout = get_cvar_float("bm_camouflagetime");
//get players team and model
new szModel[32];
new team;
cs_get_user_model(id, szModel, 32);
team = get_user_team(id);
//save current player model
gszCamouflageOldModel[id] = szModel;
//change player model depending on their current team
if (team == 1) //TERRORIST
{
cs_set_user_model(id, "urban");
}
else
{
cs_set_user_model(id, "leet");
}
//play camouflage sound
emit_sound(id, CHAN_STATIC, gszCamouflageSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
//set a task to remove camouflage after time out amount
set_task(fTimeout, "taskCamouflageRemove", TASK_CAMOUFLAGE + id, "", 0, "a", 1);
//set timers to prevent player from using camouflage again so soon
gfCamouflageTimeOut[id] = fTime + fTimeout;
gfCamouflageNextUse[id] = fTime + fTimeout + get_cvar_float("bm_camouflagecooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Camouflage next use: %.1f", gfCamouflageNextUse[id] - fTime);
}
}
actionLowGravity(id)
{
//set player to have low gravity
set_user_gravity(id, 0.25);
//set global boolean showing player has low gravity
gbLowGravity[id] = true;
}
actionFire(id, ent)
{
if (halflife_time() >= gfNextDamageTime[id])
{
new hp = get_user_health(id);
//if players health is greater than 0
if (hp > 0)
{
//if player does not have godmode
if (!get_user_godmode(id))
{
new Float:amount = get_cvar_float("bm_firedamageamount") / 10.0;
new Float:newAmount = hp - amount;
//if this amount of damage won't kill the player
if (newAmount > 0)
{
set_user_health(id, floatround(newAmount, floatround_floor));
}
else
{
//use fakedamage to kill the player
fakedamage(id, "fire block", amount, DMG_BURN);
}
}
//get halflife time and time for next fire sound from fire block
new Float:fTime = halflife_time();
new Float:fNextFireSoundTime = entity_get_float(ent, EV_FL_ltime);
//if the current time is greater than or equal to the next time to play the fire sound
if (fTime >= fNextFireSoundTime)
{
//play the fire sound
emit_sound(ent, CHAN_ITEM, gszFireSoundFlame, 0.6, ATTN_NORM, 0, PITCH_NORM);
//set the fire blocks time
entity_set_float(ent, EV_FL_ltime, fTime + 0.75);
}
//get effects vectors using block origin
new Float:origin1[3];
new Float:origin2[3];
entity_get_vector(ent, EV_VEC_origin, origin1);
entity_get_vector(ent, EV_VEC_origin, origin2);
origin1[0] -= 32.0;
origin1[1] -= 32.0;
origin1[2] += 10.0;
origin2[0] += 32.0;
origin2[1] += 32.0;
origin2[2] += 10.0;
//get a random height for the flame
new randHeight = random_num(0, 32) + 16;
//show some effects
message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
write_byte(TE_BUBBLES);
write_coord(floatround(origin1[0], floatround_floor)); //min start position
write_coord(floatround(origin1[1], floatround_floor));
write_coord(floatround(origin1[2], floatround_floor));
write_coord(floatround(origin2[0], floatround_floor)); //max start position
write_coord(floatround(origin2[1], floatround_floor));
write_coord(floatround(origin2[2], floatround_floor));
write_coord(randHeight); //float height
write_short(gSpriteIdFire); //model index
write_byte(10); //count
write_coord(1); //speed
message_end();
}
gfNextDamageTime[id] = halflife_time() + 0.05;
}
}
actionSlap(id)
{
user_slap(id, 0);
user_slap(id, 0);
set_hudmessage(0, 100, 255, -1.0, 0.20, 0, 6.0, 12.0, 0.0, 1.0, 3);
show_hudmessage(id, "GET OFF MY FACE!!!");
}
actionGrenade(id, num)
{
if(is_user_alive(id))
{
switch(num)
{
case HE:
{
if(!cs_get_user_bpammo(id, CSW_HEGRENADE) && !HeUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_hegrenade");
HeUsed[id] = true;
}
}
case SMOKE:
{
if(!cs_get_user_bpammo(id, CSW_SMOKEGRENADE) && !FrostUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_smokegrenade");
FrostUsed[id] = true;
}
}
case FLASH:
{
if(cs_get_user_bpammo(id, CSW_FLASHBANG) < 2 && !FlashUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_flashbang");
FlashUsed[id] = true;
}
}
}
}
}
actionRandom(id, ent)
{
new Float:fTime = halflife_time();
//check if player is outside of cooldown time to use camouflage
if (fTime >= gfRandomNextUse[id])
{
//get which type of block this is set to be
new blockType = entity_get_int(ent, EV_INT_iuser4);
//do the random block action
switch (blockType)
{
case BM_INVINCIBILITY: actionInvincible(id, true);
case BM_STEALTH: actionStealth(id, true);
case BM_DEATH: actionDeath(id);
case BM_CAMOUFLAGE: actionCamouflage(id, true);
case BM_SLAP: actionSlap(id);
case BM_BOOTSOFSPEED: actionBootsOfSpeed(id, true);
case BM_DEAGLE: actionDEagle(id);
case BM_SHOTGUN: actionShotgun(id);
case BM_SCOUT: actionScout(id);
case BM_AWP: actionAWP(id);
case BM_AK47: actionAk47(id);
case BM_M4A1: actionM4a1(id);
case BM_USP: actionUsp(id);
case BM_FAMAS: actionFamas(id);
case BM_GLOCK: actionGlock(id);
case BM_P90: actionP90(id);
case BM_GALIL: actionGalil(id);
}
//set timer to prevent player from using the random block again so soon
gfRandomNextUse[id] = fTime + get_cvar_float("bm_randomcooldown");
//set this random block to another random block!
new randNum = random_num(0, gRandomBlocksMax - 1);
entity_set_int(ent, EV_INT_iuser4, gRandomBlocks[randNum]);
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Random block next use: %.1f", gfRandomNextUse[id] - fTime);
}
}
actionHoney(id)
{
new taskid = TASK_HONEY + id;
//make player feel like they're stuck in honey by lowering their maxspeed
set_user_maxspeed(id, 50.0);
//remove any existing 'in honey' task
if (task_exists(taskid))
{
remove_task(taskid);
}
else
{
//half the players velocity the first time they touch it
new Float:vVelocity[3];
entity_get_vector(id, EV_VEC_velocity, vVelocity);
vVelocity[0] = vVelocity[0] / 2.0;
vVelocity[1] = vVelocity[1] / 2.0;
entity_set_vector(id, EV_VEC_velocity, vVelocity);
}
//set task to remove 'in honey' effect very soon (task replaced if player is still in honey before task time reached)
set_task(0.1, "taskNotInHoney", taskid);
}
actionBootsOfSpeed(id, bool:OverrideTimer)
{
new Float:fTime = halflife_time();
//check if player is outside of cooldown time to use the boots of speed
if (fTime >= gfBootsOfSpeedNextUse[id] || OverrideTimer)
{
new Float:fTimeout = get_cvar_float("bm_bootsofspeedtime");
//set a task to remove the boots of speed after time out amount
set_task(fTimeout, "taskBootsOfSpeedRemove", TASK_BOOTSOFSPEED + id, "", 0, "a", 1);
//set the players maxspeed to 400 so they run faster!
set_user_maxspeed(id, gfBootsMaxSpeed);
//play boots of speed sound
emit_sound(id, CHAN_STATIC, gszBootsOfSpeedSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
gfBootsOfSpeedTimeOut[id] = fTime + fTimeout;
gfBootsOfSpeedNextUse[id] = fTime + fTimeout + get_cvar_float("bm_bootsofspeedcooldown");
}
else
{
set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
show_hudmessage(id, "Boots of speed next use: %.1f", gfBootsOfSpeedNextUse[id] - fTime);
}
}
actionNoSlowDown(id)
{
new taskid = TASK_NOSLOW + id;
gbNoSlowDown[id] = true;
//remove any existing 'slow down' task
if (task_exists(taskid))
{
remove_task(taskid);
}
//set task to remove 'no slow down' effect very soon
set_task(0.1, "taskSlowDown", taskid);
}
public Flash(id){
message_begin(MSG_ONE,gMsgScreenFade,{0,0,0},id);
write_short( 1<<15 );
write_short( 1<<10 );
write_short( 1<<12 );
write_byte( 0 );
write_byte( 0 );
write_byte( 0 );
write_byte( 255 );
message_end();
}
actionFade(id){
if(is_user_alive(id)){
gMsgScreenFade = get_user_msgid("ScreenFade");
Flash(id);
}
}
actionDEagle(id)
{
if (is_user_alive(id) && !DEagleUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_deagle");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_deagle", id), 1);
DEagleUsed[id] = true;
new deaglename[42];
get_user_name(id, deaglename, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Be Careful CT! %s is running around with a Deagle!", deaglename);
ColorChat(0, TEAM_COLOR, "^4%s ^3Be Careful CT! ^4%s ^3is running around with a ^4Deagle!", gszPrefix, deaglename);
}
}
actionShotgun(id)
{
if (is_user_alive(id) && !ShotgunUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_m3");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_m3", id), 1);
ShotgunUsed[id] = true;
new shotgunname[42];
get_user_name(id, shotgunname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Be Aware CT! %s is running around with a Shotgun!", shotgunname);
ColorChat(0, TEAM_COLOR, "^4%s ^3Be Aware CT! ^4%s ^3is running around with a ^4Shotgun!", gszPrefix, shotgunname);
}
}
actionScout(id)
{
if (is_user_alive(id) && !ScoutUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_scout");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_scout", id), 1);
ScoutUsed[id] = true;
new scoutname[42];
get_user_name(id, scoutname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Be Careful CT! %s is running around with a Scout!", scoutname);
ColorChat(0, TEAM_COLOR, "^4%s ^3Be Careful CT! ^4%s ^3is running around with a ^4Scout!", gszPrefix, scoutname);
}
}
actionAWP(id)
{
if (is_user_alive(id) && !AwpUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_awp");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_awp", id), 1);
AwpUsed[id] = true;
new awpname[42];
get_user_name(id, awpname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Watch out CT! %s has picked up an AWP!", awpname);
ColorChat(0, TEAM_COLOR, "^4%s ^3Watch out CT! ^4%s ^3has picked up an ^4AWP!", gszPrefix, awpname);
}
}
actionAk47(id)
{
if (is_user_alive(id) && !Ak47Used[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_ak47");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_ak47", id), 1);
Ak47Used[id] = true;
new ak47name[42];
get_user_name(id, ak47name, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "CT is in DANGER! %s got an Ak47!", ak47name);
ColorChat(0, TEAM_COLOR, "^4%s ^3CT is in DANGER! ^4%s ^3got an ^4Ak47!", gszPrefix, ak47name);
}
}
actionM4a1(id)
{
if (is_user_alive(id) && !M4a1Used[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_m4a1");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_m4a1", id), 1);
M4a1Used[id] = true;
new m4a1name[42];
get_user_name(id, m4a1name, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Cover Your Head CT! %s has took an M4a1!", m4a1name);
ColorChat(0, TEAM_COLOR, "^4%s ^3Cover Your Head CT! ^4%s ^3has took an ^4M4a1!", gszPrefix, m4a1name);
}
}
actionUsp(id)
{
if (is_user_alive(id) && !UspUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_usp");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_usp", id), 1);
UspUsed[id] = true;
new uspname[42];
get_user_name(id, uspname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "WTF! %s has picked a USP!", uspname);
ColorChat(0, TEAM_COLOR, "^4%s WTF! ^4%s ^3has picked a ^4USP!", gszPrefix, uspname);
}
}
actionFamas(id)
{
if (is_user_alive(id) && !FamasUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_famas");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_famas", id), 1);
FamasUsed[id] = true;
new famasname[42];
get_user_name(id, famasname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Holy Shit! %s has a FAMAS!", famasname);
ColorChat(0, TEAM_COLOR, "^4%s ^3Holy Shit! ^4%s ^3Got a ^4FAMAS!", gszPrefix, famasname);
}
}
actionGlock(id)
{
if (is_user_alive(id) && !GlockUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_glock18");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_glock18", id), 1);
GlockUsed[id] = true;
new glockname[42];
get_user_name(id, glockname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Wow! %s has a Glock!", glockname);
ColorChat(0, TEAM_COLOR, "^4%s ^3WOW! ^4%s ^3Took ^4Glock!", gszPrefix, glockname);
}
}
actionP90(id)
{
if (is_user_alive(id) && !P90Used[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_p90");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_p90", id), 1);
P90Used[id] = true;
new p90name[42];
get_user_name(id, p90name, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "HIDE CT! %s has a P90!", p90name);
ColorChat(0, TEAM_COLOR, "^4%s ^3HiDE CT! ^4%s ^3has a ^4P90!", gszPrefix, p90name);
}
}
actionGalil(id)
{
if (is_user_alive(id) && !GalilUsed[id] && get_user_team(id) == 1)
{
give_item(id, "weapon_galil");
cs_set_weapon_ammo(find_ent_by_owner(1, "weapon_galil", id), 1);
GalilUsed[id] = true;
new galilname[42];
get_user_name(id, galilname, 32);
set_hudmessage(0, 100, 255, -1.0, -1.0, 0, 6.0, 4.0);
show_hudmessage(0, "Keep RUNNING CT! %s has a GAlil!", galilname);
ColorChat(0, TEAM_COLOR, "^4%s ^3Keep RUNNING CT! ^4%s ^3Got a ^4GAlil!", gszPrefix, galilname);
}
}
actionTeleport(id, ent)
{
//get end entity id
new tele = entity_get_int(ent, EV_INT_iuser1);
//if teleport end id is valid
if (tele)
{
//get end entity origin
new Float:vTele[3];
entity_get_vector(tele, EV_VEC_origin, vTele);
//if id of entity being teleported is a player and telefrags CVAR is set then kill any nearby players
if ((id > 0 && id <= 32) && get_cvar_num("bm_telefrags") > 0)
{
new player = -1;
do
{
player = find_ent_in_sphere(player, vTele, 16.0);
//if entity found is a player
if (player > 0 && player <= 32)
{
//if player is alive, and is not the player that went through the teleport
if (is_user_alive(player) && player != id)
{
//kill the player
user_kill(player, 1);
}
}
}while(player);
}
//get origin of the start of the teleport
new Float:vOrigin[3];
new origin[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin);
FVecIVec(vOrigin, origin);
//show some teleporting effects
message_begin(MSG_PVS, SVC_TEMPENTITY, origin);
write_byte(TE_IMPLOSION);
write_coord(origin[0]);
write_coord(origin[1]);
write_coord(origin[2]);
write_byte(64); // radius
write_byte(100); // count
write_byte(6); // life
message_end();
//teleport player
entity_set_vector(id, EV_VEC_origin, vTele);
//reverse players Z velocity
new Float:vVelocity[3];
entity_get_vector(id, EV_VEC_velocity, vVelocity);
vVelocity[2] = floatabs(vVelocity[2]);
entity_set_vector(id, EV_VEC_velocity, vVelocity);
//if teleport sound CVAR is set
if (get_cvar_num("bm_teleportsound") > 0)
{
//play teleport sound
emit_sound(id, CHAN_STATIC, gszTeleportSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
}
}
}
/***** TASKS *****/
public taskSupermanRemove(id)
{
id -= TASK_SUPERMAN;
if (is_user_alive(id))
{
set_user_gravity(id, 1.0);
}
}
public taskSolidNot(ent)
{
ent -= TASK_BHOPSOLIDNOT;
//make sure entity is valid
if (is_valid_ent(ent))
{
//if block isn't being grabbed
if (entity_get_int(ent, EV_INT_iuser2) == 0)
{
entity_set_int(ent, EV_INT_solid, SOLID_NOT);
set_rendering(ent, kRenderFxNone, 255, 255, 255, kRenderTransAdd, 25);
set_task(1.0, "taskSolid", TASK_BHOPSOLID + ent);
}
}
}
public taskSolid(ent)
{
ent -= TASK_BHOPSOLID;
//make sure entity is valid
if (isBlock(ent))
{
//make block solid
entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
//get the player ID of who has the block in a group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
//if the block is in a group
if (player > 0)
{
//set the block so it is now 'being grouped' (for setting the rendering)
groupBlock(0, ent);
}
else
{
new blockType = entity_get_int(ent, EV_INT_body);
set_block_rendering(ent, gRender[blockType], gRed[blockType], gGreen[blockType], gBlue[blockType], gAlpha[blockType]);
}
}
}
public taskInvincibleRemove(id)
{
id -= TASK_INVINCIBLE;
//make sure player is alive
if (is_user_alive(id))
{
set_user_godmode(id, 0);
//only set players rendering back to normal if player is not stealth
if (halflife_time() >= gfStealthTimeOut[id])
{
set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 16);
}
}
}
public taskStealthRemove(id)
{
id -= TASK_STEALTH;
//make sure player is connected
if (is_user_connected(id))
{
//only set players rendering back to normal if player is not invincible
if (halflife_time() >= gfInvincibleTimeOut[id])
{
set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 255);
}
else //if player is invincible then set player to glow white
{
set_user_rendering(id, kRenderFxGlowShell, 255, 255, 255, kRenderTransColor, 16);
}
}
}
public taskNotOnIce(id)
{
id -= TASK_ICE;
//make player run normally
entity_set_float(id, EV_FL_friction, 1.0);
if (gfOldMaxSpeed[id] > 100.0)
{
set_user_maxspeed(id, gfOldMaxSpeed[id]);
}
else
{
set_user_maxspeed(id, 250.0);
}
//no longer 'on ice'
gbOnIce[id] = false;
gfOldMaxSpeed[id] = 0.0;
}
public taskCamouflageRemove(id)
{
id -= TASK_CAMOUFLAGE;
//if player is still connected
if (is_user_connected(id))
{
//change back to players old model
cs_set_user_model(id, gszCamouflageOldModel[id]);
}
}
public taskNotInHoney(id)
{
id -= TASK_HONEY;
//if player is alive
if (is_user_alive(id))
{
//make player move normally
set_user_maxspeed(id, 250.0);
//this will set the players maxspeed faster if they have the boots of speed!
eventCurWeapon(id);
}
}
public taskBootsOfSpeedRemove(id)
{
id -= TASK_BOOTSOFSPEED;
//set players speed back to normal
if (is_user_alive(id))
{
set_user_maxspeed(id, 250.0);
}
}
public taskSlowDown(id)
{
id -= TASK_NOSLOW;
//player no longer has 'no slow down'
gbNoSlowDown[id] = false;
}
public taskSpriteNextFrame(params[])
{
new ent = params[0];
//make sure entity is valid
if (is_valid_ent(ent))
{
new frames = params[1];
new Float:current_frame = entity_get_float(ent, EV_FL_frame);
if (current_frame < 0.0 || current_frame >= frames)
{
entity_set_float(ent, EV_FL_frame, 1.0);
}
else
{
entity_set_float(ent, EV_FL_frame, current_frame + 1.0);
}
}
else
{
remove_task(TASK_SPRITE + ent);
}
}
/***** COMMANDS *****/
public cmdJump(id)
{
//if the object the player is grabbing isn't too close
if (gfGrablength[id] > 72.0)
{
//move the object closer
gfGrablength[id] -= 16.0;
}
}
public cmdDuck(id)
{
//move the object further away
gfGrablength[id] += 16.0;
}
public cmdAttack(id)
{
//if entity being grabbed is a block
if (isBlock(gGrabbed[id]))
{
//if block the player is grabbing is in their group and group count is larger than 1
if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
{
new block;
//move the rest of the blocks in the players group using vector for grabbed block
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if this block is in this players group
if (isBlockInGroup(id, block))
{
//only copy the block if it is not stuck
if (!isBlockStuck(block))
{
//copy the block
copyBlock(id, block);
}
}
}
}
else
{
//only copy the block the player has grabbed if it is not stuck
if (!isBlockStuck(gGrabbed[id]))
{
//copy the block
new newBlock = copyBlock(id, gGrabbed[id]);
//if new block was created successfully
if (newBlock)
{
//set currently grabbed block to 'not being grabbed'
entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
//set new block to 'being grabbed'
entity_set_int(newBlock, EV_INT_iuser2, id);
//set player to grabbing new block
gGrabbed[id] = newBlock;
}
}
else
{
//tell the player they can't copy a block when it is in a stuck position
ColorChat(id, TEAM_COLOR, "^4%s ^3You cannot ^4copy ^3a block that is in a ^4stuck ^3position!", gszPrefix);
}
}
}
}
public cmdAttack2(id)
{
//if player is grabbing a block
if (isBlock(gGrabbed[id]))
{
//if block the player is grabbing is in their group and group count is larger than 1
if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
{
new block;
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is still valid
if (is_valid_ent(block))
{
//if block is still in this players group
if (isBlockInGroup(id, block))
{
//delete the block
gbJustDeleted[id] = deleteBlock(block);
}
}
}
}
else
{
//delete the block
gbJustDeleted[id] = deleteBlock(gGrabbed[id]);
}
}
//if player is grabbing a teleport
else if (isTeleport(gGrabbed[id]))
{
//delete the teleport
gbJustDeleted[id] = deleteTeleport(id, gGrabbed[id]);
}
}
public cmdGrab(id)
{
//make sure player has access to use this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get the entity the player is aiming at and the length
new ent, body;
gfGrablength[id] = get_user_aiming(id, ent, body);
//set booleans depending on entity type
new bool:bIsBlock = isBlock(ent);
new bool:bIsTeleport = isTeleport(ent);
//if the entity is a block or teleport
if (bIsBlock || bIsTeleport)
{
//get who is currently grabbing the entity (if anyone)
new grabber = entity_get_int(ent, EV_INT_iuser2);
//if entity is not being grabbed by someone else
if (grabber == 0 || grabber == id)
{
//if entity is a block
if (bIsBlock)
{
//get the player ID of who has the block in a group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
//if the block is not in a group or is in this players group
if (player == 0 || player == id)
{
//set the block to 'being grabbed'
setGrabbed(id, ent);
//if this block is in this players group and group count is greater than 1
if (player == id && gGroupCount[id] > 1)
{
new Float:vGrabbedOrigin[3];
new Float:vOrigin[3];
new Float:vOffset[3];
new block;
//get origin of the block
entity_get_vector(ent, EV_VEC_origin, vGrabbedOrigin);
//iterate through all blocks in players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is still valid
if (is_valid_ent(block))
{
player = entity_get_int(ent, EV_INT_iuser1);
//if block is still in this players group
if (player == id)
{
//get origin of block in players group
entity_get_vector(block, EV_VEC_origin, vOrigin);
//calculate offset from grabbed block
vOffset[0] = vGrabbedOrigin[0] - vOrigin[0];
vOffset[1] = vGrabbedOrigin[1] - vOrigin[1];
vOffset[2] = vGrabbedOrigin[2] - vOrigin[2];
//save offset value in grouped block
entity_set_vector(block, EV_VEC_vuser1, vOffset);
//indicate that entity is being grabbed
entity_set_int(block, EV_INT_iuser2, id);
}
}
}
}
}
}
//if entity is a teleporter
else if (bIsTeleport)
{
//set the teleport to 'being grabbed'
setGrabbed(id, ent);
}
}
}
}
return PLUGIN_HANDLED;
}
setGrabbed(id, ent)
{
new Float:fpOrigin[3];
new Float:fbOrigin[3];
new Float:fAiming[3];
new iAiming[3];
new bOrigin[3];
//get players current view model then clear it
entity_get_string(id, EV_SZ_viewmodel, gszViewModel[id], 32);
entity_set_string(id, EV_SZ_viewmodel, "");
get_user_origin(id, bOrigin, 1); //position from eyes (weapon aiming)
get_user_origin(id, iAiming, 3); //end position from eyes (hit point for weapon)
entity_get_vector(id, EV_VEC_origin, fpOrigin); //get player position
entity_get_vector(ent, EV_VEC_origin, fbOrigin); //get block position
IVecFVec(iAiming, fAiming);
FVecIVec(fbOrigin, bOrigin);
//set gGrabbed
gGrabbed[id] = ent;
gvGrabOffset[id][0] = fbOrigin[0] - iAiming[0];
gvGrabOffset[id][1] = fbOrigin[1] - iAiming[1];
gvGrabOffset[id][2] = fbOrigin[2] - iAiming[2];
//indicate that entity is being grabbed
entity_set_int(ent, EV_INT_iuser2, id);
}
public cmdRelease(id)
{
//make sure player has access to use this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//if player is grabbing an entity
if (gGrabbed[id])
{
//if entity player is grabbing is a block
if (isBlock(gGrabbed[id]))
{
//if block the player is grabbing is in their group and group count is > 1
if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
{
new block;
new bool:bGroupIsStuck = true;
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if this block is in this players group
if (isBlockInGroup(id, block))
{
//indicate that entity is no longer being grabbed
entity_set_int(block, EV_INT_iuser2, 0);
//start off thinking all blocks in group are stuck
if (bGroupIsStuck)
{
//if block is not stuck
if (!isBlockStuck(block))
{
//at least one of the blocks in the group are not stuck
bGroupIsStuck = false;
}
}
}
}
//if all the blocks in the group are stuck
if (bGroupIsStuck)
{
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if this block is in this players group
if (isBlockInGroup(id, block))
{
//delete the block
deleteBlock(block);
}
}
//tell the player all the blocks were deleted because they were stuck
ColorChat(id, TEAM_COLOR, "^4%s ^3Group ^4deleted ^3because all the blocks were ^4stuck!", gszPrefix);
}
}
else
{
//if block player has grabbed is valid
if (is_valid_ent(gGrabbed[id]))
{
//if the block is stuck
if (isBlockStuck(gGrabbed[id]))
{
//delete the block
new bool:bDeleted = deleteBlock(gGrabbed[id]);
//if the block was deleted successfully
if (bDeleted)
{
//tell the player the block was deleted and why
ColorChat(0, GREEN, "^x03%s^x04 Block^x01 deleted because it was ^x04stuck!", gszPrefix);
}
}
else
{
//indicate that the block is no longer being grabbed
entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
}
}
}
}
else if (isTeleport(gGrabbed[id]))
{
//indicate that the teleport is no longer being grabbed
entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
}
//set the players view model back to what it was
entity_set_string(id, EV_SZ_viewmodel, gszViewModel[id]);
//indicate that player is not grabbing an object
gGrabbed[id] = 0;
}
}
return PLUGIN_HANDLED;
}
/* MENUS */
public showMainMenu(id)
{
new col[3];
new szMenu[256];
new szGodmode[6];
new szNoclip[6];
col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
szNoclip = (get_user_noclip(id) ? "\yOn" : "\rOff");
szGodmode = (get_user_godmode(id) ? "\yOn" : "\rOff");
//format the main menu
format(szMenu, 256, gszMainMenu, col, szNoclip, col, szGodmode);
//show the main menu to the player
show_menu(id, gKeysMainMenu, szMenu, -1, "bmMainMenu");
return PLUGIN_HANDLED;
}
showBlockMenu(id)
{
new col[3];
new szMenu[256];
new szGodmode[6];
new szNoclip[6];
new szSize[8];
col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
szNoclip = (get_user_noclip(id) ? "\yOn" : "\rOff");
szGodmode = (get_user_godmode(id) ? "\yOn" : "\rOff");
switch (gBlockSize[id])
{
case SMALL: szSize = "Small";
case NORMAL: szSize = "Normal";
case LARGE: szSize = "Large";
case POLE: szSize = "Pole";
}
//format the main menu
format(szMenu, 256, gszBlockMenu, gszBlockNames[gSelectedBlockType[id]], col, col, col, col, col, szNoclip, col, szGodmode, szSize);
//show the block menu to the player
show_menu(id, gKeysBlockMenu, szMenu, -1, "bmBlockMenu");
return PLUGIN_HANDLED;
}
showBlockSelectionMenu(id)
{
//create block selection menu 1 (first 8 blocks)
new szBlockMenu[256];
new szTitle[32];
new szEntry[32];
new num;
new startBlock;
//format the page number into the menu title
format(szTitle, sizeof(szTitle), "\yBlock Selection %d^n^n", gBlockMenuPage[id]);
//add the title to the menu
add(szBlockMenu, sizeof(szBlockMenu), szTitle);
//calculate the block that the menu will start on
startBlock = (gBlockMenuPage[id] - 1) * 8;
//iterate through 8 blocks to add to the menu
for (new i = startBlock; i < startBlock + 8; ++i)
{
//make sure the loop doesn't go above the maximum number of blocks
if (i < gBlockMax)
{
//calculate the menu item number
num = (i - startBlock) + 1;
//format the block name into the menu entry
format(szEntry, sizeof(szEntry), "\r%d. \w%s^n", num, gszBlockNames[i]);
}
else
{
//format a blank menu entry
format(szEntry, sizeof(szEntry), "^n");
}
//add the entry to the menu
add(szBlockMenu, sizeof(szBlockMenu), szEntry);
}
//if the block selection page the player is on is less than the maximum page
if (gBlockMenuPage[id] < gBlockMenuPagesMax)
{
add(szBlockMenu, sizeof(szBlockMenu), "^n\r9. \wMore");
}
else
{
add(szBlockMenu, sizeof(szBlockMenu), "^n");
}
//add a back option to the menu
add(szBlockMenu, sizeof(szBlockMenu), "^n\r0. \wBack");
//display the block selection menu
show_menu(id, gKeysBlockSelectionMenu, szBlockMenu, -1, "bmBlockSelectionMenu");
}
showTeleportMenu(id)
{
new col[3];
new szMenu[256];
new szGodmode[6];
new szNoclip[6];
col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
szNoclip = (get_user_noclip(id) ? "\yOn" : "\rOff");
szGodmode = (get_user_godmode(id) ? "\yOn" : "\rOff");
//format teleport menu
format(szMenu, sizeof(szMenu), gszTeleportMenu, col, (gTeleportStart[id] ? "\w" : "\d"), col, col, col, col, szNoclip, col, szGodmode);
show_menu(id, gKeysTeleportMenu, szMenu, -1, "bmTeleportMenu");
}
showOptionsMenu(id, oldMenu)
{
//set the oldmenu global variable so when the back key is pressed it goes back to the previous menu
gMenuBeforeOptions[id] = oldMenu;
new col[3];
new szSnapping[6];
new szMenu[256];
col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
szSnapping = (gbSnapping[id] ? "\yOn" : "\rOff");
//format the options menu
format(szMenu, sizeof(szMenu), gszOptionsMenu, col, szSnapping, col, gfSnappingGap[id], col, col, col, col, col, col);
//show the options menu to the player
show_menu(id, gKeysOptionsMenu, szMenu, -1, "bmOptionsMenu");
}
showChoiceMenu(id, gChoice, const szTitle[96])
{
gChoiceOption[id] = gChoice;
//format choice menu using given title
new szMenu[128];
format(szMenu, sizeof(szMenu), gszChoiceMenu, szTitle);
//show the choice menu to the player
show_menu(id, gKeysChoiceMenu, szMenu, -1, "bmChoiceMenu");
}
public handleMainMenu(id, num)
{
switch (num)
{
case N1: { showBlockMenu(id); }
case N2: { showTeleportMenu(id); }
case N6: { toggleNoclip(id); }
case N7: { toggleGodmode(id); }
case N9: { showOptionsMenu(id, 1); }
case N0: { return; }
}
//selections 1, 2, 3, 4, 5 and 9 show different menus
if (num != N1 && num != N2 && num != N3 && num != N4 && num!= N5 && num != N9)
{
//display menu again
showMainMenu(id);
}
}
public handleBlockMenu(id, num)
{
switch (num)
{
case N1: { showBlockSelectionMenu(id); }
case N2: { createBlockAiming(id, gSelectedBlockType[id]); }
case N3: { convertBlockAiming(id, gSelectedBlockType[id]); }
case N4: { deleteBlockAiming(id); }
case N5: { rotateBlockAiming(id); }
case N6: { toggleNoclip(id); }
case N7: { toggleGodmode(id); }
case N8: { changeBlockSize(id); }
case N9: { showOptionsMenu(id, 2); }
case N0: { showMainMenu(id); }
}
//selections 1, 9 and 0 show different menus
if (num != N1 && num != N9 && num != N0)
{
//display menu again
showBlockMenu(id);
}
}
public handleBlockSelectionMenu(id, num)
{
switch (num)
{
case N9:
{
//goto next block selection menu page
++gBlockMenuPage[id];
//make sure the player can't go above the maximum block selection page
if (gBlockMenuPage[id] > gBlockMenuPagesMax)
{
gBlockMenuPage[id] = gBlockMenuPagesMax;
}
//show block selection menu again
showBlockSelectionMenu(id);
}
case N0:
{
//goto previous block selection menu page
--gBlockMenuPage[id];
//show block menu if player goes back too far
if (gBlockMenuPage[id] < 1)
{
showBlockMenu(id);
gBlockMenuPage[id] = 1;
}
else
{
//show block selection menu again
showBlockSelectionMenu(id);
}
}
default:
{
//offset the num value using the players block selection page number
num += (gBlockMenuPage[id] - 1) * 8;
//if block number is within range
if (num < gBlockMax)
{
gSelectedBlockType[id] = num;
showBlockMenu(id);
}
else
{
showBlockSelectionMenu(id);
}
}
}
}
public handleTeleportMenu(id, num)
{
switch (num)
{
case N1: { createTeleportAiming(id, TELEPORT_START); }
case N2: { createTeleportAiming(id, TELEPORT_END); }
case N3: { swapTeleportAiming(id); }
case N4: { deleteTeleportAiming(id); }
case N5: { showTeleportPath(id); }
case N6: { toggleNoclip(id); }
case N7: { toggleGodmode(id); }
case N9: { showOptionsMenu(id, 3); }
case N0: { showMainMenu(id); }
}
//selections 9 and 0 show different menus
if (num != N9 && num != N0)
{
showTeleportMenu(id);
}
}
public handleOptionsMenu(id, num)
{
switch (num)
{
case N1: { toggleSnapping(id); }
case N2: { toggleSnappingGap(id); }
case N3: { groupBlockAiming(id); }
case N4: { groupClear(id); }
case N5: { showChoiceMenu(id, CHOICE_DEL_BLOCKS, "Are you sure you want to erase all blocks on the map?"); }
case N6: { showChoiceMenu(id, CHOICE_DEL_TELEPORTS, "Are you sure you want to erase all teleports on the map?"); }
case N7: { saveBlocks(id); }
case N8: { showChoiceMenu(id, CHOICE_LOAD, "Loading will erase all blocks and teleports, do you want to continue?"); }
case N9: { showHelp(id); }
case N0: //back to previous menu
{
switch (gMenuBeforeOptions[id])
{
case 1: showMainMenu(id);
case 2: showBlockMenu(id);
case 3: showTeleportMenu(id);
//for some reason the players 'gMenuBeforeOptions' number is invalid
default: log_amx("%sPlayer ID: %d has an invalid gMenuBeforeOptions: %d", gszPrefix, id, gMenuBeforeOptions[id]);
}
}
}
//these selections show a different menu
if (num != N5 && num != N6 && num != N8 && num != N0)
{
//display menu again
showOptionsMenu(id, gMenuBeforeOptions[id]);
}
}
public handleChoiceMenu(id, num)
{
switch (num)
{
case N1: //YES
{
switch (gChoiceOption[id])
{
case CHOICE_LOAD: loadBlocks(id);
case CHOICE_DEL_BLOCKS: deleteAllBlocks(id, true);
case CHOICE_DEL_TELEPORTS: deleteAllTeleports(id, true);
default:
{
log_amx("%sInvalid choice in handleChoiceMenu()", gszPrefix);
}
}
}
}
//show options menu again
showOptionsMenu(id, gMenuBeforeOptions[id]);
}
toggleGodmode(id)
{
new szPlayerName[32];
get_user_name(id, szPlayerName, 32);
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//if player has godmode
if (get_user_godmode(id))
{
//turn off godmode for player
set_user_godmode(id, 0);
gbAdminGodmode[id] = false;
ColorChat(0, GREEN, "^x03[staNioN-MM]^x04 %s^x01 Has^x04 Disabled^x01 godmode!", szPlayerName);
}
else
{
//turn on godmode for player
set_user_godmode(id, 1);
gbAdminGodmode[id] = true;
ColorChat(0, TEAM_COLOR, "^x03[staNioN-MM]^x04 %s^x01 Has^x04 Enabled^x01 godmode!", szPlayerName);
}
}
}
toggleNoclip(id)
{
new szPlayerName[32];
get_user_name(id, szPlayerName, 32);
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//if player has noclip
if (get_user_noclip(id))
{
//turn off noclip for player
set_user_noclip(id, 0);
gbAdminNoclip[id] = false;
ColorChat(0, GREEN, "^x03[staNioN-MM]^x04 %s^x01 Has^x04 Disabled^x01 noclip!", szPlayerName);
}
else
{
//turn on noclip for player
set_user_noclip(id, 1);
gbAdminNoclip[id] = true;
ColorChat(0, GREEN, "^x03[staNioN-MM]^x04 %s^x01 Has^x04 Enabled^x01 noclip!", szPlayerName);
}
}
}
changeBlockSize(id)
{
switch (gBlockSize[id])
{
case SMALL: gBlockSize[id] = NORMAL;
case NORMAL: gBlockSize[id] = LARGE;
case LARGE: gBlockSize[id] = POLE;
case POLE: gBlockSize[id] = SMALL;
}
}
toggleSnapping(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
gbSnapping[id] = !gbSnapping[id];
}
}
toggleSnappingGap(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//increment this players snapping gap by 5
gfSnappingGap[id] += 4.0;
//if this players snapping gap gets too big then loop it back to 0
if (gfSnappingGap[id] > 40.0)
{
gfSnappingGap[id] = 0.0;
}
}
}
showHelp(id)
{
//get cvar values
new szHelpText[1600];
new Telefrags = get_cvar_num("bm_telefrags");
new Float:fFireDamageAmount = get_cvar_float("bm_firedamageamount");
new Float:fDamageAmount = get_cvar_float("bm_damageamount");
new Float:fHealAmount = get_cvar_float("bm_healamount");
new Float:fInvincibleTime = get_cvar_float("bm_invincibletime");
new Float:fInvincibleCooldown = get_cvar_float("bm_invinciblecooldown");
new Float:fStealthTime = get_cvar_float("bm_stealthtime");
new Float:fStealthCooldown = get_cvar_float("bm_stealthcooldown");
new Float:fCamouflageTime = get_cvar_float("bm_camouflagetime");
new Float:fCamouflageCooldown = get_cvar_float("bm_camouflagecooldown");
new Float:fRandomCooldown = get_cvar_float("bm_randomcooldown");
new Float:fBootsOfSpeedTime = get_cvar_float("bm_bootsofspeedtime");
new Float:fBootsOfSpeedCooldown = get_cvar_float("bm_bootsofspeedcooldown");
new TeleportSound = get_cvar_num("bm_teleportsound");
//format the help text
format(szHelpText, sizeof(szHelpText), gszHelpText, Telefrags, fFireDamageAmount, fDamageAmount, fHealAmount, fInvincibleTime, fInvincibleCooldown, fStealthTime, fStealthCooldown, fCamouflageTime, fCamouflageCooldown, fRandomCooldown, fBootsOfSpeedTime, fBootsOfSpeedCooldown, TeleportSound);
//show the help
show_motd(id, szHelpText, gszHelpTitle);
}
showTeleportPath(id)
{
//get the entity the player is aiming at
new ent, body;
get_user_aiming(id, ent, body);
//if entity found is a teleport
if (isTeleport(ent))
{
//get other side of teleport
new tele = entity_get_int(ent, EV_INT_iuser1);
//if there is another end to the teleport
if (tele)
{
//get origins of the start and end teleport entities
new life = 50;
new Float:vOrigin1[3];
new Float:vOrigin2[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin1);
entity_get_vector(tele, EV_VEC_origin, vOrigin2);
//draw a line in between the 2 origins
drawLine(vOrigin1, vOrigin2, life);
//get the distance between the points
new Float:fDist = get_distance_f(vOrigin1, vOrigin2);
//notify that a line has been drawn between the start and end of the teleport
ColorChat(id, TEAM_COLOR, "^4%s ^3A line has been ^4drawn ^3to show the ^4teleport path. ^3Distance: ^4%f ^3units.", gszPrefix, fDist);
}
}
}
/* GROUPING BLOCKS */
groupBlockAiming(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get the entity the player is aiming at
new ent, body;
get_user_aiming(id, ent, body);
//is entity is a block
if (isBlock(ent))
{
//get whether or not block is already being grouped
new player = entity_get_int(ent, EV_INT_iuser1);
//if block is not in a group
if (player == 0)
{
//increment group value
++gGroupCount[id];
//add this entity to the players group
gGroupedBlocks[id][gGroupCount[id]] = ent;
//set the block so it is now 'being grouped'
groupBlock(id, ent);
}
//if block is in this players group
else if (player == id)
{
//remove block from being grouped
groupRemoveBlock(ent);
}
//if another player has the block grouped
else
{
//get id and name of who has the block grouped
new szName[32];
new player = entity_get_int(ent, EV_INT_iuser1);
get_user_name(player, szName, 32);
//notify player who the block is being grouped by
ColorChat(id, TEAM_COLOR, "^4%s ^3Block is ^4already ^3in a group by: ^4%s", gszPrefix, szName);
}
}
}
}
groupBlock(id, ent)
{
//if entity is valid
if (is_valid_ent(ent))
{
//if id passed in is a player
if (id > 0 && id <= 32)
{
//set block so it is now being grouped
entity_set_int(ent, EV_INT_iuser1, id);
}
//make block glow red to show it is grouped
set_rendering(ent, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 16);
}
}
groupRemoveBlock(ent)
{
//make sure entity is a block
if (isBlock(ent))
{
//remove block from being grouped (stays in players gGroupedBlocks[id][] array
entity_set_int(ent, EV_INT_iuser1, 0);
//get block type
new blockType = entity_get_int(ent, EV_INT_body);
//set rendering on block
set_block_rendering(ent, gRender[blockType], gRed[blockType], gGreen[blockType], gBlue[blockType], gAlpha[blockType]);
}
}
groupClear(id)
{
new blockCount = 0;
new blocksDeleted = 0;
new block;
//remove all players blocks from being grouped
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is in this players group
if (isBlockInGroup(id, block))
{
//if block is stuck
if (isBlockStuck(block))
{
//delete the stuck block
deleteBlock(block);
//count how many blocks have been deleted
++blocksDeleted;
}
else
{
//remove block from being grouped
groupRemoveBlock(block);
//count how many blocks have been removed from group
++blockCount;
}
}
}
//set players group count to 0
gGroupCount[id] = 0;
//if player is connected
if (is_user_connected(id))
{
//if some blocks were deleted
if (blocksDeleted > 0)
{
//notify player how many blocks were cleared from group and deleted
ColorChat(id, TEAM_COLOR, "^4%s ^3Removed ^4%d ^3blocks from group, deleted ^4%d stuck ^3blocks", gszPrefix, blockCount, blocksDeleted);
}
else
{
//notify player how many blocks were cleared from group
ColorChat(id, TEAM_COLOR, "^4%s ^3Removed ^4%d ^3blocks from group", gszPrefix, blockCount);
}
}
}
/* BLOCK & TELEPORT OPERATIONS */
moveGrabbedEntity(id, Float:vMoveTo[3] = {0.0, 0.0, 0.0})
{
new iOrigin[3], iLook[3];
new Float:fOrigin[3], Float:fLook[3], Float:fDirection[3], Float:fLength;
get_user_origin(id, iOrigin, 1); //Position from eyes (weapon aiming)
get_user_origin(id, iLook, 3); //End position from eyes (hit point for weapon)
IVecFVec(iOrigin, fOrigin);
IVecFVec(iLook, fLook);
fDirection[0] = fLook[0] - fOrigin[0];
fDirection[1] = fLook[1] - fOrigin[1];
fDirection[2] = fLook[2] - fOrigin[2];
fLength = get_distance_f(fLook, fOrigin);
if (fLength == 0.0) fLength = 1.0; //avoid division by 0
//calculate the position to move the block
vMoveTo[0] = (fOrigin[0] + fDirection[0] * gfGrablength[id] / fLength) + gvGrabOffset[id][0];
vMoveTo[1] = (fOrigin[1] + fDirection[1] * gfGrablength[id] / fLength) + gvGrabOffset[id][1];
vMoveTo[2] = (fOrigin[2] + fDirection[2] * gfGrablength[id] / fLength) + gvGrabOffset[id][2];
vMoveTo[2] = float(floatround(vMoveTo[2], floatround_floor));
//move the block and its sprite (if it has one)
moveEntity(id, gGrabbed[id], vMoveTo, true);
}
moveEntity(id, ent, Float:vMoveTo[3], bool:bDoSnapping)
{
//if entity is a block
if (isBlock(ent))
{
//do snapping for entity if snapping boolean passed in is true
if (bDoSnapping)
{
doSnapping(id, ent, vMoveTo);
}
//set the position of the block
entity_set_origin(ent, vMoveTo);
//get the sprite that sits above the block (if any)
new sprite = entity_get_int(ent, EV_INT_iuser3);
//if sprite entity is valid
if (sprite)
{
//get size of block
new Float:vSizeMax[3];
entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
//move the sprite onto the top of the block
vMoveTo[2] += vSizeMax[2] + 0.15;
entity_set_origin(sprite, vMoveTo);
}
}
else
{
//set the position of the entity
entity_set_origin(ent, vMoveTo);
}
}
/* TELEPORTS */
createTeleportAiming(const id, const teleportType)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get where player is aiming for origin of teleport entity
new pOrigin[3], Float:vOrigin[3];
get_user_origin(id, pOrigin, 3);
IVecFVec(pOrigin, vOrigin);
vOrigin[2] += gfTeleportZOffset;
//create the teleport of the given type
createTeleport(id, teleportType, vOrigin);
}
}
createTeleport(const id, const teleportType, Float:vOrigin[3])
{
new ent = create_entity(gszInfoTarget);
if (is_valid_ent(ent))
{
switch (teleportType)
{
case TELEPORT_START:
{
//if player has already created a teleport start entity then delete it
if (gTeleportStart[id])
{
remove_entity(gTeleportStart[id]);
}
//set teleport properties
entity_set_string(ent, EV_SZ_classname, gszTeleportStartClassname);
entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
entity_set_model(ent, gszTeleportSpriteStart);
entity_set_size(ent, gfTeleportSizeMin, gfTeleportSizeMax);
entity_set_origin(ent, vOrigin);
//set the rendermode and transparency
entity_set_int(ent, EV_INT_rendermode, 5); //rendermode
entity_set_float(ent, EV_FL_renderamt, 255.0); //visable
//set task for animating sprite
new params[2];
params[0] = ent;
params[1] = gTeleportStartFrames;
set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + ent, params, 2, "b");
//store teleport start entity to a global variable so it can be linked to the end entity
gTeleportStart[id] = ent;
}
case TELEPORT_END:
{
//make sure there is a teleport start entity
if (gTeleportStart[id])
{
//set teleport properties
entity_set_string(ent, EV_SZ_classname, gszTeleportEndClassname);
entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
entity_set_model(ent, gszTeleportSpriteEnd);
entity_set_size(ent, gfTeleportSizeMin, gfTeleportSizeMax);
entity_set_origin(ent, vOrigin);
//set the rendermode and transparency
entity_set_int(ent, EV_INT_rendermode, 5); //rendermode
entity_set_float(ent, EV_FL_renderamt, 255.0); //visable
//link up teleport start and end entities
entity_set_int(ent, EV_INT_iuser1, gTeleportStart[id]);
entity_set_int(gTeleportStart[id], EV_INT_iuser1, ent);
//set task for animating sprite
new params[2];
params[0] = ent;
params[1] = gTeleportEndFrames;
set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + ent, params, 2, "b");
//indicate that this player has no teleport start entity waiting for an end
gTeleportStart[id] = 0;
}
else
{
//delete entity that was created because there is no start entity
remove_entity(ent);
}
}
}
}
else
{
log_amx("%sCouldn't create 'env_sprite' entity", gszPrefix);
}
}
swapTeleportAiming(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get entity that player is aiming at
new ent, body;
get_user_aiming(id, ent, body, 9999);
//swap teleport start and destination
if (isTeleport(ent))
{
swapTeleport(id, ent);
}
}
}
swapTeleport(id, ent)
{
new Float:vOriginEnt[3];
new Float:vOriginTele[3];
//get the other end of the teleport
new tele = entity_get_int(ent, EV_INT_iuser1);
//if the teleport has another side
if (is_valid_ent(tele))
{
//get teleport properties
entity_get_vector(ent, EV_VEC_origin, vOriginEnt);
entity_get_vector(tele, EV_VEC_origin, vOriginTele);
new szClassname[32];
entity_get_string(ent, EV_SZ_classname, szClassname, 32);
//delete old teleport
deleteTeleport(id, ent);
//create new teleport at opposite positions
if (equal(szClassname, gszTeleportStartClassname))
{
createTeleport(id, TELEPORT_START, vOriginTele);
createTeleport(id, TELEPORT_END, vOriginEnt);
}
else if (equal(szClassname, gszTeleportEndClassname))
{
createTeleport(id, TELEPORT_START, vOriginEnt);
createTeleport(id, TELEPORT_END, vOriginTele);
}
}
else
{
//tell player they cant swap because its only 1 sided
ColorChat(0, TEAM_COLOR, "%s^3Can't ^4swap ^3teleport positions", gszPrefix);
}
}
deleteTeleportAiming(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get entity that player is aiming at
new ent, body;
get_user_aiming(id, ent, body, 9999);
//delete block that player is aiming at
new bool:deleted = deleteTeleport(id, ent);
if (deleted)
{
ColorChat(0, TEAM_COLOR, "^4%s^3Teleport ^4deleted!", gszPrefix);
}
}
}
bool:deleteTeleport(id, ent)
{
//if entity is a teleport then delete both the start and the end of the teleport
if (isTeleport(ent))
{
//get entity id of the other side of the teleport
new tele = entity_get_int(ent, EV_INT_iuser1);
//clear teleport start entity if it was just deleted
if (gTeleportStart[id] == ent || gTeleportStart[id] == tele)
{
gTeleportStart[id] = 0;
}
//remove tasks that exist to animate the teleport sprites
if (task_exists(TASK_SPRITE + ent))
{
remove_task(TASK_SPRITE + ent);
}
if (task_exists(TASK_SPRITE + tele))
{
remove_task(TASK_SPRITE + tele);
}
//delete both the start and end positions of the teleporter
if (tele)
{
remove_entity(tele);
}
remove_entity(ent);
//delete was deleted
return true;
}
//teleport was not deleted
return false;
}
/* OPTIONS */
deleteAllBlocks(id, bool:bNotify)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
new bool:bDeleted;
new blockCount = 0;
new ent = -1;
//find all blocks in the map
while ((ent = find_ent_by_class(ent, gszBlockClassname)))
{
//delete the block
bDeleted = deleteBlock(ent);
//if block was successfully deleted
if (bDeleted)
{
//increment counter for how many blocks have been deleted
++blockCount;
}
}
//if some blocks were deleted
if (blockCount > 0)
{
//get players name
new szName[32];
get_user_name(id, szName, 32);
//iterate through all players
for (new i = 1; i <= 32; ++i)
{
//make sure nobody is grabbing a block because they've all been deleted!
gGrabbed[id] = 0;
//make sure player is connected
if (is_user_connected(i))
{
//notify all admins that the player deleted all the blocks
if (bNotify && get_user_flags(i) & BM_ADMIN_LEVEL)
{
ColorChat(0, GREEN, "^x03%s^x04'%s'^x01 deleted all the^x04 blocks^x01 from the map. Total blocks: ^x03%d", gszPrefix, szName, blockCount);
}
}
}
}
}
}
deleteAllTeleports(id, bool:bNotify)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
new bool:bDeleted;
new teleCount = 0;
new ent = -1;
//find all teleport start entities in the map
while ((ent = find_ent_by_class(ent, gszTeleportStartClassname)))
{
//delete the teleport
bDeleted = deleteTeleport(id, ent);
//if teleport was successfully deleted
if (bDeleted)
{
//increment counter for how many teleports have been deleted
++teleCount;
}
}
//if some teleports were deleted
if (teleCount > 0)
{
//get players name
new szName[32];
get_user_name(id, szName, 32);
//iterate through all players
for (new i = 1; i <= 32; ++i)
{
//make sure nobody has a teleport start set
gTeleportStart[id] = 0;
//make sure player is connected
if (is_user_connected(i))
{
//notify all admins that the player deleted all the teleports
if (bNotify && get_user_flags(i) & BM_ADMIN_LEVEL)
{
ColorChat(0, GREEN, "^x03%s^x04'%s'^x01 deleted all the ^x04teleports^x01 from the map. Total teleports: ^x03%d", gszPrefix, szName, teleCount);
}
}
}
}
}
}
/***** BLOCKS *****/
createBlockAiming(const id, const blockType)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
new origin[3];
new Float:vOrigin[3];
new szCreator[32];
get_user_name(id, szCreator, 31);
replace_all(szCreator, 31, " ", "_");
//get the origin of the player and add Z offset
get_user_origin(id, origin, 3);
IVecFVec(origin, vOrigin);
vOrigin[2] += gfBlockSizeMaxForZ[2];
//create the block
createBlock(id, blockType, vOrigin, Z, gBlockSize[id], szCreator);
}
}
createBlock(const id, const blockType, Float:vOrigin[3], const axis, const size, szCreator[] = "Unknown")
{
new ent = create_entity(gszInfoTarget);
//make sure entity was created successfully
if (is_valid_ent(ent))
{
//set block properties
entity_set_string(ent, EV_SZ_classname, gszBlockClassname);
entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
new Float:vSizeMin[3];
new Float:vSizeMax[3];
new Float:vAngles[3];
new Float:fScale;
new szBlockModel[256];
//set mins, maxs and angles depending on axis
switch (axis)
{
case X:
{
if (size == POLE) {
vSizeMin = gfPoleBlockSizeMinForX;
vSizeMax = gfPoleBlockSizeMaxForX;
} else {
vSizeMin = gfBlockSizeMinForX;
vSizeMax = gfBlockSizeMaxForX;
}
vAngles[0] = 90.0;
}
case Y:
{
if (size == POLE) {
vSizeMin = gfPoleBlockSizeMinForY;
vSizeMax = gfPoleBlockSizeMaxForY;
} else {
vSizeMin = gfBlockSizeMinForY;
vSizeMax = gfBlockSizeMaxForY;
}
vAngles[0] = 90.0;
vAngles[2] = 90.0;
}
case Z:
{
if (size == POLE) {
vSizeMin = gfPoleBlockSizeMinForZ;
vSizeMax = gfPoleBlockSizeMaxForZ;
} else {
vSizeMin = gfBlockSizeMinForZ;
vSizeMax = gfBlockSizeMaxForZ;
}
vAngles = gfDefaultBlockAngles;
}
}
//set block model name and scale depending on size
switch (size)
{
case SMALL:
{
setBlockModelNameSmall(szBlockModel, gszBlockModels[blockType], 256);
fScale = SCALE_SMALL;
}
case NORMAL:
{
szBlockModel = gszBlockModels[blockType];
fScale = SCALE_NORMAL;
}
case LARGE:
{
setBlockModelNameLarge(szBlockModel, gszBlockModels[blockType], 256);
fScale = SCALE_LARGE;
}
case POLE:
{
setBlockModelNamePole(szBlockModel, gszBlockModels[blockType], 256);
}
}
//adjust size min/max vectors depending on scale
if (size != POLE) {
for (new i = 0; i < 3; ++i)
{
if (vSizeMin[i] != 4.0 && vSizeMin[i] != -4.0)
{
vSizeMin[i] *= fScale;
}
if (vSizeMax[i] != 4.0 && vSizeMax[i] != -4.0)
{
vSizeMax[i] *= fScale;
}
}
}
//if it's a valid block type
if (blockType >= 0 && blockType < gBlockMax)
{
entity_set_model(ent, szBlockModel);
}
else
{
entity_set_model(ent, gszBlockModelDefault);
}
entity_set_vector(ent, EV_VEC_angles, vAngles);
entity_set_size(ent, vSizeMin, vSizeMax);
entity_set_int(ent, EV_INT_body, blockType);
//if a player is creating the block
if (id > 0 && id <= 32)
{
//do snapping for new block
doSnapping(id, ent, vOrigin);
}
//set origin of new block
entity_set_origin(ent, vOrigin);
// Set creator
set_pev(ent, pev_targetname, szCreator, 31);
//setup special properties for the random block
if (blockType == BM_RANDOM)
{
//set this random block to a random block!
new randNum = random_num(0, gRandomBlocksMax - 1);
entity_set_int(ent, EV_INT_iuser4, gRandomBlocks[randNum]);
}
//set rendering on block
set_block_rendering(ent, gRender[blockType], gRed[blockType], gGreen[blockType], gBlue[blockType], gAlpha[blockType]);
//if blocktype is one which requires an additional sprite
if (blockType == BM_FIRE)
{
//add sprite on top of the block
new sprite = create_entity(gszInfoTarget);
//make sure entity was created successfully
if (sprite)
{
//create angle vector and rotate it so its horizontal
new Float:vAngles[3];
vAngles[0] = 90.0;
vAngles[1] = 0.0;
vAngles[2] = 0.0;
//move the sprite up onto the top of the block, adding 0.15 to prevent flickering
vOrigin[2] += vSizeMax[2] + 0.15;
//set block properties
entity_set_string(sprite, EV_SZ_classname, gszSpriteClassname);
entity_set_int(sprite, EV_INT_solid, SOLID_NOT);
entity_set_int(sprite, EV_INT_movetype, MOVETYPE_NONE);
entity_set_vector(sprite, EV_VEC_angles, vAngles);
//set the rendermode to additive and set the transparency
entity_set_int(sprite, EV_INT_rendermode, 5);
entity_set_float(sprite, EV_FL_renderamt, 255.0);
//set origin of new sprite
entity_set_origin(sprite, vOrigin);
//link this sprite to the block
entity_set_int(ent, EV_INT_iuser3, sprite);
//set task for animating the sprite
if (blockType == BM_FIRE)
{
new params[2];
params[0] = sprite;
params[1] = 8; //both the fire and trampoline sprites have 8 frames
set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + sprite, params, 2, "b");
}
}
}
return ent;
}
return 0;
}
convertBlockAiming(id, const convertTo)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get entity that player is aiming at
new ent, body;
get_user_aiming(id, ent, body);
//if player is aiming at a block
if (isBlock(ent))
{
//get who is currently grabbing the block (if anyone)
new grabber = entity_get_int(ent, EV_INT_iuser2);
//if entity is not being grabbed by someone else
if (grabber == 0 || grabber == id)
{
//get the player ID of who has the block in a group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
//if the block is not in a group or is in this players group
if (player == 0 || player == id)
{
new newBlock;
//if block is in the players group and group count is larger than 1
if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
{
new block;
new blockCount = 0;
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if this block is in this players group
if (isBlockInGroup(id, block))
{
//convert the block
newBlock = convertBlock(id, block, convertTo, true);
//if block was converted
if (newBlock != 0)
{
//new block is now in the group
gGroupedBlocks[id][i] = newBlock;
//set the block so it is now 'being grouped'
groupBlock(id, newBlock);
}
//count how many blocks could NOT be converted
else
{
++blockCount;
}
}
}
//if some blocks could NOT be converted
if (blockCount > 1)
{
ColorChat(id, TEAM_COLOR, "^4%s ^3Couldn't convert ^4%d ^3blocks!", gszPrefix, blockCount);
}
}
else
{
new szCreator[32];
get_user_name(id, szCreator, 31);
replace_all(szCreator, 31, " ", "_");
newBlock = convertBlock(id, ent, convertTo, false, szCreator);
//if block was not converted
if (newBlock == 0)
{
//get the block type
new blockType = entity_get_int(ent, EV_INT_body);
ColorChat(id, TEAM_COLOR, "^4%s ^3You cannot ^4convert ^3a ^4%s ^3block into a ^4%s ^3block while it is ^4rotated!", gszPrefix, gszBlockNames[blockType], gszBlockNames[convertTo]);
}
}
}
else
{
//get name of player who has this block in their group
new szName[32];
get_user_name(player, szName, 32);
//notify player who has this block in their group
ColorChat(id, TEAM_COLOR, "^4%s ^4%s ^3currently has this block in their ^4group!", gszPrefix, szName);
}
}
}
}
}
convertBlock(id, ent, const convertTo, const bool:bPreserveSize, szCreator[] = "Unknown")
{
new blockType;
new Float:vOrigin[3];
new Float:vSizeMax[3];
new axis;
//get block information from block player is aiming at
blockType = entity_get_int(ent, EV_INT_body);
entity_get_vector(ent, EV_VEC_origin, vOrigin);
entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
//work out the axis orientation
for (new i = 0; i < 3; ++i)
{
if (vSizeMax[i] == 4.0)
{
axis = i;
break;
}
}
//if block is rotated and we're trying to convert it to a block that cannot be rotated
if ((axis == X || axis == Y) && !isBlockTypeRotatable(blockType))
{
return 0;
}
else
{
//delete old block and create new one of given type
deleteBlock(ent);
if (bPreserveSize)
{
//work out the block size
new size = SMALL;
new Float:fMax = vSizeMax[0] + vSizeMax[1] + vSizeMax[2];
if (fMax > 36.0) size = POLE;
if (fMax > 64.0) size = NORMAL;
if (fMax > 128.0) size = LARGE;
return createBlock(id, convertTo, vOrigin, axis, size, szCreator);
}
else
{
return createBlock(id, convertTo, vOrigin, axis, gBlockSize[id], szCreator);
}
}
return ent;
}
deleteBlockAiming(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get entity that player is aiming at
new ent, body;
get_user_aiming(id, ent, body);
//if entity player is aiming at is a block
if (isBlock(ent))
{
//get who is currently grabbing the block (if anyone)
new grabber = entity_get_int(ent, EV_INT_iuser2);
//if entity is not being grabbed by someone else
if (grabber == 0 || grabber == id)
{
//get the player ID of who has the block in a group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
//if the block is not in a group or is in this players group
if (player == 0 || player == id)
{
//if block is not being grabbed
if (entity_get_int(ent, EV_INT_iuser2) == 0)
{
//if block is in the players group and group count is larger than 1
if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
{
new block;
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is still valid
if (is_valid_ent(block))
{
//get player id of who has this block in their group
new player = entity_get_int(block, EV_INT_iuser1);
//if block is still in this players group
if (player == id)
{
//delete the block
deleteBlock(block);
}
}
}
}
else
{
//delete the block
deleteBlock(ent);
}
}
}
else
{
//get name of player who has this block in their group
new szName[32];
get_user_name(player, szName, 32);
//notify player who has this block in their group
ColorChat(id, TEAM_COLOR, "^4%s %s ^3currently has this ^4block ^3in their ^4group!", gszPrefix, szName);
}
}
}
}
}
bool:deleteBlock(ent)
{
//if entity is a block
if (isBlock(ent))
{
//get the sprite attached to the top of the block
new sprite = entity_get_int(ent, EV_INT_iuser3);
//if sprite entity is valid
if (sprite)
{
//remove the task for the animation of the sprite (if one exists)
if (task_exists(TASK_SPRITE + sprite))
{
remove_task(TASK_SPRITE + sprite);
}
//delete the sprite
remove_entity(sprite);
}
//delete the block
remove_entity(ent);
//block was deleted
return true;
}
//block was not deleted
return false;
}
rotateBlockAiming(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
//get block that player is aiming at
new ent, body;
get_user_aiming(id, ent, body);
//if entity found is a block
if (isBlock(ent))
{
//get who is currently grabbing the block (if anyone)
new grabber = entity_get_int(ent, EV_INT_iuser2);
//if entity is not being grabbed by someone else
if (grabber == 0 || grabber == id)
{
//get the player ID of who has the block in a group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
//if the block is not in a group or is in this players group
if (player == 0 || player == id)
{
//if block is in the players group and group count is larger than 1
if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
{
new block;
new bool:bRotateGroup = true;
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is in players group
if (isBlockInGroup(id, block))
{
//get block type
new blockType = entity_get_int(block, EV_INT_body);
//if block cannot be rotated
if (!isBlockTypeRotatable(blockType))
{
//found a block that cannot be rotated
bRotateGroup = false;
break;
}
}
}
//if we can rotate the group
if (bRotateGroup)
{
//iterate through all blocks in the players group
for (new i = 0; i <= gGroupCount[id]; ++i)
{
block = gGroupedBlocks[id][i];
//if block is still valid
if (isBlockInGroup(id, block))
{
//rotate the block
rotateBlock(block);
}
}
}
else
{
//notify player that their group cannot be rotated
ColorChat(id, TEAM_COLOR, "^4%s ^3Your ^4group ^3contains blocks that cannot be ^4rotated!", gszPrefix);
}
}
else
{
//rotate the block and get rotated block ID
new bool:bRotatedBlock = rotateBlock(ent);
//if block did not rotate successfully
if (!bRotatedBlock)
{
//get block type
new blockType = entity_get_int(ent, EV_INT_body);
//notify player block couldn't rotate
ColorChat(id, TEAM_COLOR, "^4%s %s ^3blocks cannot be ^4rotated!", gszPrefix, gszBlockNames[blockType]);
}
}
}
else
{
//get name of player who has this block in their group
new szName[32];
get_user_name(player, szName, 32);
//notify player who has this block in their group
ColorChat(id, TEAM_COLOR, "^4%s %s ^3currently has this block in their ^4group!", gszPrefix, szName);
}
}
}
}
}
bool:rotateBlock(ent)
{
//if entity is valid
if (is_valid_ent(ent))
{
//get block type
new blockType = entity_get_int(ent, EV_INT_body);
//if block is a type that can be rotated (a block without a sprite, makes it easier!)
if (isBlockTypeRotatable(blockType))
{
new Float:vAngles[3];
new Float:vSizeMin[3];
new Float:vSizeMax[3];
new Float:fTemp;
//get block information
entity_get_vector(ent, EV_VEC_angles, vAngles);
entity_get_vector(ent, EV_VEC_mins, vSizeMin);
entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
//create new block using current block information with new angles and sizes
if (vAngles[0] == 0.0 && vAngles[2] == 0.0)
{
vAngles[0] = 90.0;
}
else if (vAngles[0] == 90.0 && vAngles[2] == 0.0)
{
vAngles[0] = 90.0;
vAngles[2] = 90.0;
}
else
{
vAngles = gfDefaultBlockAngles;
}
//shift vector values along
fTemp = vSizeMin[0];
vSizeMin[0] = vSizeMin[2];
vSizeMin[2] = vSizeMin[1];
vSizeMin[1] = fTemp;
fTemp = vSizeMax[0];
vSizeMax[0] = vSizeMax[2];
vSizeMax[2] = vSizeMax[1];
vSizeMax[1] = fTemp;
//set the blocks new angle
entity_set_vector(ent, EV_VEC_angles, vAngles);
//set the blocks new size
entity_set_size(ent, vSizeMin, vSizeMax);
return true;
}
}
return false;
}
copyBlock(id, ent)
{
//if entity is valid
if (is_valid_ent(ent))
{
new Float:vOrigin[3];
new Float:vAngles[3];
new Float:vSizeMin[3];
new Float:vSizeMax[3];
new Float:fMax;
new blockType;
new size;
new axis;
new szCreator[32];
get_user_name(id, szCreator, 31);
replace_all(szCreator, 31, " ", "_");
//get blocktype and origin of currently grabbed block
blockType = entity_get_int(ent, EV_INT_body);
entity_get_vector(ent, EV_VEC_origin, vOrigin);
entity_get_vector(ent, EV_VEC_angles, vAngles);
entity_get_vector(ent, EV_VEC_mins, vSizeMin);
entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
//work out the block size
size = SMALL;
fMax = vSizeMax[0] + vSizeMax[1] + vSizeMax[2];
if (fMax > 36.0) size = POLE;
if (fMax > 64.0) size = NORMAL;
if (fMax > 128.0) size = LARGE;
if (size == POLE) {
if (vSizeMin[0] == gfPoleBlockSizeMinForX[0] && vSizeMin[1] == gfPoleBlockSizeMinForX[1] && vSizeMin[2] == gfPoleBlockSizeMinForX[2] && vSizeMax[0] == gfPoleBlockSizeMaxForX[0] && vSizeMax[1] == gfPoleBlockSizeMaxForX[1] && vSizeMax[2] == gfPoleBlockSizeMaxForX[2]) {
axis = X;
} else if (vSizeMin[0] == gfPoleBlockSizeMinForY[0] && vSizeMin[1] == gfPoleBlockSizeMinForY[1] && vSizeMin[2] == gfPoleBlockSizeMinForY[2] && vSizeMax[0] == gfPoleBlockSizeMaxForY[0] && vSizeMax[1] == gfPoleBlockSizeMaxForY[1] && vSizeMax[2] == gfPoleBlockSizeMaxForY[2]) {
axis = Y;
} else if (vSizeMin[0] == gfPoleBlockSizeMinForZ[0] && vSizeMin[1] == gfPoleBlockSizeMinForZ[1] && vSizeMin[2] == gfPoleBlockSizeMinForZ[2] && vSizeMax[0] == gfPoleBlockSizeMaxForZ[0] && vSizeMax[1] == gfPoleBlockSizeMaxForZ[1] && vSizeMax[2] == gfPoleBlockSizeMaxForZ[2]) {
axis = Z;
}
} else {
//work out the axis orientation
for (new i = 0; i < 3; ++i)
{
if (vSizeMax[i] == 4.0)
{
axis = i;
break;
}
}
}
//create a block of the same type in the same location
return createBlock(0, blockType, vOrigin, axis, size, szCreator);
}
return 0;
}
set_block_rendering(ent, type, red, green, blue, alpha)
{
if (isBlock(ent))
{
switch (type)
{
case GLOWSHELL: set_rendering(ent, kRenderFxGlowShell, red, green, blue, kRenderNormal, alpha);
case TRANSCOLOR: set_rendering(ent, kRenderFxGlowShell, red, green, blue, kRenderTransColor, alpha);
case TRANSALPHA: set_rendering(ent, kRenderFxNone, red, green, blue, kRenderTransColor, alpha);
case TRANSWHITE: set_rendering(ent, kRenderFxNone, red, green, blue, kRenderTransAdd, alpha);
default: set_rendering(ent, kRenderFxNone, red, green, blue, kRenderNormal, alpha);
}
}
}
/* BLOCK TESTS */
bool:isBlockInGroup(id, ent)
{
//is entity valid
if (is_valid_ent(ent))
{
//get player who has this block in their group (if anyone)
new player = entity_get_int(ent, EV_INT_iuser1);
if (player == id)
{
return true;
}
}
return false;
}
bool:isBlockTypeRotatable(blockType)
{
if (blockType != BM_FIRE)
{
return true;
}
return false;
}
bool:isBlock(ent)
{
//is it a valid entity
if (is_valid_ent(ent))
{
//get classname of entity
new szClassname[32];
entity_get_string(ent, EV_SZ_classname, szClassname, 32);
//if classname of entity matches global block classname
if (equal(szClassname, gszBlockClassname) || equal(szClassname, "bcm"))
{
//entity is a block
return true;
}
}
//entity is not a block
return false;
}
bool:isBlockStuck(ent)
{
//first make sure the entity is valid
if (is_valid_ent(ent))
{
new content;
new Float:vOrigin[3];
new Float:vPoint[3];
new Float:fSizeMin[3];
new Float:fSizeMax[3];
//get the size of the block being grabbed
entity_get_vector(ent, EV_VEC_mins, fSizeMin);
entity_get_vector(ent, EV_VEC_maxs, fSizeMax);
//get the origin of the block
entity_get_vector(ent, EV_VEC_origin, vOrigin);
//decrease the size values of the block
fSizeMin[0] += 1.0;
fSizeMax[0] -= 1.0;
fSizeMin[1] += 1.0;
fSizeMax[1] -= 1.0;
fSizeMin[2] += 1.0;
fSizeMax[2] -= 1.0;
//get the contents of the centre of all 6 faces of the block
for (new i = 0; i < 14; ++i)
{
//start by setting the point to the origin of the block (the middle)
vPoint = vOrigin;
//set the values depending on the loop number
switch (i)
{
//corners
case 0: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMax[2]; }
case 1: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMax[2]; }
case 2: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMax[2]; }
case 3: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMax[2]; }
case 4: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMin[2]; }
case 5: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMin[2]; }
case 6: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMin[2]; }
case 7: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMin[2]; }
//centre of faces
case 8: { vPoint[0] += fSizeMax[0]; }
case 9: { vPoint[0] += fSizeMin[0]; }
case 10: { vPoint[1] += fSizeMax[1]; }
case 11: { vPoint[1] += fSizeMin[1]; }
case 12: { vPoint[2] += fSizeMax[2]; }
case 13: { vPoint[2] += fSizeMin[2]; }
}
//get the contents of the point on the block
content = point_contents(vPoint);
//if the point is out in the open
if (content == CONTENTS_EMPTY || content == 0)
{
//block is not stuck
return false;
}
}
}
else
{
//entity is invalid but don't say its stuck
return false;
}
//block is stuck
return true;
}
bool:isTeleport(ent)
{
if (is_valid_ent(ent))
{
//get classname of entity
new szClassname[32];
entity_get_string(ent, EV_SZ_classname, szClassname, 32);
//compare classnames
if (equal(szClassname, gszTeleportStartClassname) || equal(szClassname, gszTeleportEndClassname))
{
//entity is a teleport
return true;
}
}
//entity is not a teleport
return false;
}
doSnapping(id, ent, Float:fMoveTo[3])
{
//if player has snapping enabled
if (gbSnapping[id])
{
new Float:fSnapSize = gfSnapDistance + gfSnappingGap[id];
new Float:vReturn[3];
new Float:dist;
new Float:distOld = 9999.9;
new Float:vTraceStart[3];
new Float:vTraceEnd[3];
new tr;
new trClosest = 0;
new blockFace;
//get the size of the block being grabbed
new Float:fSizeMin[3];
new Float:fSizeMax[3];
entity_get_vector(ent, EV_VEC_mins, fSizeMin);
entity_get_vector(ent, EV_VEC_maxs, fSizeMax);
//do 6 traces out from each face of the block
for (new i = 0; i < 6; ++i)
{
//setup the start of the trace
vTraceStart = fMoveTo;
switch (i)
{
case 0: vTraceStart[0] += fSizeMin[0]; //edge of block on -X
case 1: vTraceStart[0] += fSizeMax[0]; //edge of block on +X
case 2: vTraceStart[1] += fSizeMin[1]; //edge of block on -Y
case 3: vTraceStart[1] += fSizeMax[1]; //edge of block on +Y
case 4: vTraceStart[2] += fSizeMin[2]; //edge of block on -Z
case 5: vTraceStart[2] += fSizeMax[2]; //edge of block on +Z
}
//setup the end of the trace
vTraceEnd = vTraceStart;
switch (i)
{
case 0: vTraceEnd[0] -= fSnapSize;
case 1: vTraceEnd[0] += fSnapSize;
case 2: vTraceEnd[1] -= fSnapSize;
case 3: vTraceEnd[1] += fSnapSize;
case 4: vTraceEnd[2] -= fSnapSize;
case 5: vTraceEnd[2] += fSnapSize;
}
//trace a line out from one of the block faces
tr = trace_line(ent, vTraceStart, vTraceEnd, vReturn);
//if the trace found a block and block is not in group or block to snap to is not in group
if (isBlock(tr) && (!isBlockInGroup(id, tr) || !isBlockInGroup(id, ent)))
{
//get the distance from the grabbed block to the found block
dist = get_distance_f(vTraceStart, vReturn);
//if distance to found block is less than the previous block
if (dist < distOld)
{
trClosest = tr;
distOld = dist;
//save the block face where the trace came from
blockFace = i;
}
}
}
//if there is a block within the snapping range
if (is_valid_ent(trClosest))
{
//get origin of closest block
new Float:vOrigin[3];
entity_get_vector(trClosest, EV_VEC_origin, vOrigin);
//get sizes of closest block
new Float:fTrSizeMin[3];
new Float:fTrSizeMax[3];
entity_get_vector(trClosest, EV_VEC_mins, fTrSizeMin);
entity_get_vector(trClosest, EV_VEC_maxs, fTrSizeMax);
//move the subject block to the origin of the closest block
fMoveTo = vOrigin;
//offset the block to be on the side where the trace hit the closest block
if (blockFace == 0) fMoveTo[0] += (fTrSizeMax[0] + fSizeMax[0]) + gfSnappingGap[id];
if (blockFace == 1) fMoveTo[0] += (fTrSizeMin[0] + fSizeMin[0]) - gfSnappingGap[id];
if (blockFace == 2) fMoveTo[1] += (fTrSizeMax[1] + fSizeMax[1]) + gfSnappingGap[id];
if (blockFace == 3) fMoveTo[1] += (fTrSizeMin[1] + fSizeMin[1]) - gfSnappingGap[id];
if (blockFace == 4) fMoveTo[2] += (fTrSizeMax[2] + fSizeMax[2]) + gfSnappingGap[id];
if (blockFace == 5) fMoveTo[2] += (fTrSizeMin[2] + fSizeMin[2]) - gfSnappingGap[id];
}
}
}
/***** FILE HANDLING *****/
saveBlocks(id)
{
//make sure player has access to this command
if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
new file = fopen(gszNewFile, "wt");
new ent = -1;
new blockType;
new Float:vOrigin[3];
new Float:vAngles[3];
new Float:vStart[3];
new Float:vEnd[3];
new blockCount = 0;
new teleCount = 0;
new szData[128];
new Float:fMax;
new size;
new Float:vSizeMax[3];
new szNameCreator[32];
while ((ent = find_ent_by_class(ent, gszBlockClassname)))
{
//get block info
blockType = entity_get_int(ent, EV_INT_body);
entity_get_vector(ent, EV_VEC_origin, vOrigin);
entity_get_vector(ent, EV_VEC_angles, vAngles);
entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
size = SMALL;
fMax = vSizeMax[0] + vSizeMax[1] + vSizeMax[2];
if (fMax > 36.0) size = POLE;
if (fMax > 64.0) size = NORMAL;
if (fMax > 128.0) size = LARGE;
pev(ent, pev_targetname, szNameCreator, 31);
//format block info and save it to file
formatex(szData, 128, "%c %f %f %f %f %f %f %d %s^n", gBlockSaveIds[blockType], vOrigin[0], vOrigin[1], vOrigin[2], vAngles[0], vAngles[1], vAngles[2], size, szNameCreator);
fputs(file, szData);
//increment block count
++blockCount;
}
//iterate through teleport end entities because you can't have an end without a start
ent = -1;
while ((ent = find_ent_by_class(ent, gszTeleportEndClassname)))
{
//get the id of the start of the teleporter
new tele = entity_get_int(ent, EV_INT_iuser1);
//check that start of teleport is a valid entity
if (tele)
{
//get the origin of the start of the teleport and save it to file
entity_get_vector(tele, EV_VEC_origin, vStart);
entity_get_vector(ent, EV_VEC_origin, vEnd);
formatex(szData, 128, "%c %f %f %f %f %f %f^n", gTeleportSaveId, vStart[0], vStart[1], vStart[2], vEnd[0], vEnd[1], vEnd[2]);
fputs(file, szData);
//2 teleport entities count as 1 teleporter
++teleCount;
}
}
//get players name
new szName[32];
get_user_name(id, szName, 32);
//notify all admins that the player saved blocks to file
for (new i = 1; i <= 32; ++i)
{
//make sure player is connected
if (is_user_connected(i))
{
if (get_user_flags(i) & BM_ADMIN_LEVEL)
{
ColorChat(0, GREEN, "^x03%s^x04'%s'^x01 saved %d^x04 block%s^x01, %d ^x04teleporter%s^x01 Total entites in map:^x04 %d", gszPrefix, szName, blockCount, (blockCount == 1 ? "" : "s"), teleCount, (teleCount == 1 ? "" : "s"), entity_count());
}
}
}
//close file
fclose(file);
}
}
loadBlocks(id)
{
new bool:bAccess = false;
//if this function was called on map load, ID is 0
if (id == 0)
{
bAccess = true;
}
//make sure user calling this function has access
else if (get_user_flags(id) & BM_ADMIN_LEVEL)
{
bAccess = true;
}
if (bAccess)
{
//if map file exists
if (file_exists(gszNewFile))
{
//if a player is loading then first delete all the old blocks, teleports and timers
if (id > 0 && id <= 32)
{
deleteAllBlocks(id, false);
deleteAllTeleports(id, false);
}
new szData[128];
new szType[2];
new sz1[16], sz2[16], sz3[16], sz4[16], sz5[16], sz6[16], sz7[16];
new Float:vVec1[3];
new Float:vVec2[3];
new axis;
new size;
new f = fopen(gszNewFile, "rt");
new blockCount = 0;
new teleCount = 0;
new szCreator[32];
//iterate through all the lines in the file
while (!feof(f))
{
szType = "";
fgets(f, szData, 128);
parse(szData, szType, 1, sz1, 16, sz2, 16, sz3, 16, sz4, 16, sz5, 16, sz6, 16, sz7, 16, szCreator, 31);
vVec1[0] = str_to_float(sz1);
vVec1[1] = str_to_float(sz2);
vVec1[2] = str_to_float(sz3);
vVec2[0] = str_to_float(sz4);
vVec2[1] = str_to_float(sz5);
vVec2[2] = str_to_float(sz6);
size = str_to_num(sz7);
if (strlen(szType) > 0)
{
//if type is not a teleport
if (szType[0] != gTeleportSaveId)
{
//set axis orientation depending on block angles
if (vVec2[0] == 90.0 && vVec2[1] == 0.0 && vVec2[2] == 0.0)
{
axis = X;
}
else if (vVec2[0] == 90.0 && vVec2[1] == 0.0 && vVec2[2] == 90.0)
{
axis = Y;
}
else
{
axis = Z;
}
//increment block counter
++blockCount;
}
//create block or teleport depending on type
switch (szType[0])
{
case 'A': createBlock(0, BM_PLATFORM, vVec1, axis, size, szCreator);
case 'B': createBlock(0, BM_BHOP, vVec1, axis, size, szCreator);
case 'C': createBlock(0, BM_DAMAGE, vVec1, axis, size, szCreator);
case 'D': createBlock(0, BM_HEALER, vVec1, axis, size, szCreator);
case 'E': createBlock(0, BM_INVINCIBILITY, vVec1, axis, size, szCreator);
case 'F': createBlock(0, BM_STEALTH, vVec1, axis, size, szCreator);
case 'H': createBlock(0, BM_SPEEDBOOST, vVec1, axis, size, szCreator);
case 'I': createBlock(0, BM_NOFALLDAMAGE, vVec1, axis, size, szCreator);
case 'J': createBlock(0, BM_ICE, vVec1, axis, size, szCreator);
case 'K': createBlock(0, BM_DEATH, vVec1, axis, size, szCreator);
case 'M': createBlock(0, BM_CAMOUFLAGE, vVec1, axis, size, szCreator);
case 'N': createBlock(0, BM_LOWGRAVITY, vVec1, axis, size, szCreator);
case 'O': createBlock(0, BM_FIRE, vVec1, axis, size, szCreator);
case 'P': createBlock(0, BM_SLAP, vVec1, axis, size, szCreator);
case 'Q': createBlock(0, BM_RANDOM, vVec1, axis, size, szCreator);
case 'R': createBlock(0, BM_HONEY, vVec1, axis, size, szCreator);
case 'S': createBlock(0, BM_BARRIER_CT, vVec1, axis, size, szCreator);
case 'T': createBlock(0, BM_BARRIER_T, vVec1, axis, size, szCreator);
case 'U': createBlock(0, BM_BOOTSOFSPEED, vVec1, axis, size, szCreator);
case 'V': createBlock(0, BM_GLASS, vVec1, axis, size, szCreator);
case 'X': createBlock(0, BM_GLASS_IGZ, vVec1, axis, size, szCreator);
case '+': createBlock(0, BM_GLASS_NORMAL, vVec1, axis, size, szCreator);
case 'W': createBlock(0, BM_BHOP_NOSLOW, vVec1, axis, size, szCreator);
case '$': createBlock(0, BM_DELAYEDBHOP, vVec1, axis, size, szCreator);
case '<': createBlock(0, BM_FADE, vVec1, axis, size, szCreator);
case '#': createBlock(0, BM_DEAGLE, vVec1, axis, size, szCreator);
case 'Y': createBlock(0, BM_HE, vVec1, axis, size, szCreator);
case 'Z': createBlock(0, BM_SMOKE, vVec1, axis, size, szCreator);
case '!': createBlock(0, BM_FLASH, vVec1, axis, size, szCreator);
case '@': createBlock(0, BM_AWP, vVec1, axis, size, szCreator);
case 'G': createBlock(0, BM_TRAMPOLINE_MID, vVec1, axis, size, szCreator);
case '=': createBlock(0, BM_TRAMPOLINE_LOW, vVec1, axis, size, szCreator);
case ')': createBlock(0, BM_TRAMPOLINE_HIGH, vVec1, axis, size, szCreator);
case '(': createBlock(0, BM_LIGHT, vVec1, axis, size, szCreator);
case '4': createBlock(0, BM_NOFALLDAMAGEBHOP, vVec1, axis, size, szCreator);
case '9': createBlock(0, BM_DUCK, vVec1, axis, size, szCreator);
case '7': createBlock(0, BM_MONEY, vVec1, axis, size, szCreator);
case '8': createBlock(0, BM_SUPERMAN, vVec1, axis, size, szCreator);
case '&': createBlock(0, BM_XP, vVec1, axis, size, szCreator);
case '2': createBlock(0, BM_SHOTGUN, vVec1, axis, size, szCreator);
case '3': createBlock(0, BM_SCOUT, vVec1, axis, size, szCreator);
case '>': createBlock(0, BM_AK47, vVec1, axis, size, szCreator);
case ']': createBlock(0, BM_M4A1, vVec1, axis, size, szCreator);
case '[': createBlock(0, BM_USP, vVec1, axis, size, szCreator);
case '.': createBlock(0, BM_FAMAS, vVec1, axis, size, szCreator);
case '_': createBlock(0, BM_GLOCK, vVec1, axis, size, szCreator);
case '?': createBlock(0, BM_P90, vVec1, axis, size, szCreator);
case '|': createBlock(0, BM_GALIL, vVec1, axis, size, szCreator);
case gTeleportSaveId:
{
createTeleport(0, TELEPORT_START, vVec1);
createTeleport(0, TELEPORT_END, vVec2);
//increment teleport count
++teleCount;
}
default:
{
log_amx("%sInvalid block type: %c in: %s", gszPrefix, szType[0], gszFile);
//decrement block counter because a block was not created
--blockCount;
}
}
}
}
fclose(f);
//if a player is loading the blocks
if (id > 0 && id <= 32)
{
//get players name
new szName[32];
get_user_name(id, szName, 32);
//notify all admins that the player loaded blocks from file
for (new i = 1; i <= 32; ++i)
{
//make sure player is connected
if (is_user_connected(i))
{
if (get_user_flags(i) & BM_ADMIN_LEVEL)
{
ColorChat(0, GREEN, "^x03%s^x04'%s'^x01 loaded %d^x04 block%s^x01, %d ^x04teleporter%s^x01 Total entites in map:^x04 %d", gszPrefix, szName, blockCount, (blockCount == 1 ? "" : "s"), teleCount, (teleCount == 1 ? "" : "s"), entity_count());
}
}
}
}
}
else
{
//if a player is loading the blocks
if (id > 0 && id <= 32)
{
//notify player that the file could not be found
client_print(id, print_chat, "%sCouldn't find file: %s", gszPrefix, gszNewFile);
}
}
}
}
/* MISC */
drawLine(Float:vOrigin1[3], Float:vOrigin2[3], life)
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
write_byte(TE_BEAMPOINTS);
write_coord(floatround(vOrigin1[0], floatround_floor));
write_coord(floatround(vOrigin1[1], floatround_floor));
write_coord(floatround(vOrigin1[2], floatround_floor));
write_coord(floatround(vOrigin2[0], floatround_floor));
write_coord(floatround(vOrigin2[1], floatround_floor));
write_coord(floatround(vOrigin2[2], floatround_floor));
write_short(gSpriteIdBeam); //sprite index
write_byte(0); //starting frame
write_byte(1); //frame rate in 0.1's
write_byte(life); //life in 0.1's
write_byte(5); //line width in 0.1's
write_byte(0); //noise amplitude in 0.01's
write_byte(255); //red
write_byte(255); //green
write_byte(255); //blue
write_byte(255); //brightness
write_byte(0); //scroll speed in 0.1's
message_end();
}
/* XP Information */
native hnsxp_get_user_xp(client);
native hnsxp_set_user_xp(client, xp);
stock hnsxp_add_user_xp(client, xp)
{
return hnsxp_set_user_xp(client, hnsxp_get_user_xp(client) + xp);
}
Last edited by staNioN; 07-31-2014 at 13:52.
Reason: code changed
|
|