Правила форума Гаранты форума
Размещение рекламы AMX-X компилятор

Здравствуйте, гость Вход | Регистрация

Наши новости:

14-дек
24-апр
10-апр
11-апр

3 страниц V   1 2 »

Помощь с Пушками

Статус пользователя Templar
сообщение 2.3.2015, 12:02
Сообщение #1
Иконка группы

Стаж: 18 лет

Сообщений: 2680
Благодарностей: 978
Полезность: 860

Меценат Меценат

Добрый день.
Можно как то сделать так, что бы игроки не могли разбить пушки из своей же команды?

Скрытый текст

#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fun>
#include <cstrike>
#include <fakemeta>
#include <cssb/war3ft_natives.inc>
#include <cssb/messages.inc>

#if defined DEBUG
#include <amxmisc>
#endif

#define MAXSENTRIESTOTAL 20
#define MAXPLAYERSENTRIES get_pcvar_num(iCvarSentryMax) // how many sentries each player can build
#define DMG_EXPLOSION_TAKE 90 // how much HP at most an exploding sentry takes from a player - the further away the less dmg is dealt to player
#define SENTRYEXPLODERADIUS 250.0 // how far away it is safe to be from an exploding sentry without getting kicked back and hurt
#define THINKFIREFREQUENCY 0.1 // the rate in seconds between each bullet when firing at a locked target
#define SENTRYTILTRADIUS 830.0 // likely you won't need to touch this. it's how accurate the cannon will aim at the target vertically (up/down, just for looks, aim is calculated differently)
#if !defined DEBUG
#define DISALLOW_OWN_UPGRADES // you cannot upgrade your own sentry to level 2 (only to level 3 if someone else upgraded it already) (only have this commented in debug mode)
#define DISALLOW_TWO_UPGRADES // the upgrader cannot upgrade again, builder must upgrade to level 3 (only have this commented in debug mode)
#endif
#define EXPLODINGSENTRIES // comment this out if you don't want the sentries to explode, push people away and hurt them (should now be stable!)

// Bots will build sentries at objective critical locations (around dropped bombs, at bomb targets, near hostages etc)
// They can also build randomly around maps using these values:
#define BOT_WAITTIME_MIN 0.0 // waittime = the time a bot will wait after he's decided to build a sentry, before actually building (seconds)
#define BOT_WAITTIME_MAX 15.0
#define BOT_NEXT_MIN 0.0 // next = after building a sentry, this specifies the time a bot will wait until considering about waittime again (seconds)
#define BOT_NEXT_MAX 120.0

// These are per sentry level, 1-3
new const g_SENTRYFRAGREWARDS[3] = {3000,1500,500} // how many money you get if your sentry frags someone.
new const g_DMG[3] = {50, 100, 170} // how much damage a bullet from a sentry does per hit
new const Float:g_THINKFREQUENCIES[3] = {3.0, 1.5, 0.8} // how often, in seconds, a sentry searches for targets when not locked at a target, a lower value means a sentry will lock on targets faster
new const Float:g_HITRATIOS[3] = {0.5, 0.65, 0.75} // how good a sentry is at hitting its target. 1.0 = always hit, 0.0 = never hit
new const Float:g_HEALTHS[3] = {550.0, 1100.0, 2200.0} // how many HP a sentry has. Increase to make sentry sturdier

#if !defined PI
#define PI 3.141592654 // feel free to find a PI more exact than this
#endif


#define MAXHTMLSIZE 1536
#define MAXSENTRIES 32 * MAXSENTRIESTOTAL

#define SENTRY_VEC_PEOPLE EV_VEC_vuser1
#define OWNER 0
#define UPGRADER_1 1
#define UPGRADER_2 2

GetSentryPeople(sentry, who)
{
new Float:people[3]
entity_get_vector(sentry, SENTRY_VEC_PEOPLE, people)
return floatround(people[who])
}

SetSentryPeople(sentry, who, is)
{
new Float:people[3]
entity_get_vector(sentry, SENTRY_VEC_PEOPLE, people)
people[who] = is + 0.0
entity_set_vector(sentry, SENTRY_VEC_PEOPLE, people)
}

#define SENTRY_ENT_TARGET EV_ENT_euser1
#define SENTRY_ENT_BASE EV_ENT_euser2
#define SENTRY_ENT_SPYCAM EV_ENT_euser3
#define SENTRY_INT_FIRE EV_INT_iuser1
#define SENTRY_INT_TEAM EV_INT_iuser2
#define SENTRY_INT_LEVEL EV_INT_iuser3
#define SENTRY_INT_PENDDIR EV_INT_iuser4 // 1st bit: sentry cannon, 2nd bit: radar
#define SENTRY_FL_ANGLE EV_FL_fuser1
#define SENTRY_FL_SPINSPEED EV_FL_fuser2
#define SENTRY_FL_MAXSPIN EV_FL_fuser3
#define SENTRY_FL_RADARANGLE EV_FL_fuser4

// These are bits used in SENTRY_INT_PENDDIR
#define SENTRY_DIR_CANNON 0
#define SENTRY_DIR_RADAR 1

#define BASE_ENT_SENTRY EV_ENT_euser1
#define BASE_INT_TEAM EV_INT_iuser1

#define SENTRY_LEVEL_1 0
#define SENTRY_LEVEL_2 1
#define SENTRY_LEVEL_3 2
#define SENTRY_FIREMODE_NO 0
#define SENTRY_FIREMODE_YES 1
#define SENTRY_FIREMODE_NUTS 2
#define TASKID_SENTRYFIRE 1000
#define TASKID_BOTBUILDRANDOMLY 2000
#define TASKID_SENTRYSTATUS 3000
#define TASKID_THINK 4000
#define TASKID_THINKPENDULUM 5000
#define TASKID_SENTRYONRADAR 6000
#define TASKID_SPYCAM 7000
#define DUCKINGPLAYERDIFFERENCE 18.0
#define TARGETUPMODIFIER DUCKINGPLAYERDIFFERENCE // if player ducks on ground, traces don't hit...
#define DMG_BULLET (1<<1) // shot
#define DMG_BLAST (1<<6) // explosive blast damage
#define TE_EXPLFLAG_NONE 0
#define TE_EXPLOSION 3
#define TE_TRACER 6
#define TE_BREAKMODEL 108
#define BASESENTRYDELAY 2.0 // seconds from base is built until sentry top appears
#define PENDULUM_MAX 45.0 // how far sentry turret turns in each direction when idle, before turning back
#define PENDULUM_INCREMENT 10.0 // speed of turret turning...
#define RADAR_INCREMENT 2.0 // speed of small radar turning on top of sentry level 3...
#define MAXUPGRADERANGE 75.0 // farthest distance to sentry you can upgrade using upgrade command
#define COLOR_BOTTOM_CT 160 // default bottom colour of CT:s sentries
#define COLOR_TOP_CT 150 // default top colour of CT:s sentries
#define COLOR_BOTTOM_T 0 // default bottom colour of T:s sentries
#define COLOR_TOP_T 0 // default top colour of T:s sentries
#define SENTRYSHOCKPOWER 3.0 // multiplier, increase to make exploding sentries throw stuff further away
#define CANNONHEIGHTFROMFEET 20.0 // tweakable to make tracer originate from the same height as the sentry's cannon. Also traces rely on this Y-wise offset.
#define PLAYERORIGINHEIGHT 36.0 // this is the distance from a player's EV_VEC_origin to ground, if standing up
#define HEIGHTDIFFERENCEALLOWED 20.0 // increase value to allow building in slopes with higher angles. You can set to 0.0 and you will only be able to build on exact flat ground. note: mostly applies to downhill building, uphill is still likely to "collide" with ground...

// This cannot account for sentries which are still under construction (only base, no sentry head yet):
// How many (or more) sentries:
#define BOT_MAXSENTRIESNEAR 1

// cannot be in the vicinity of this radius:
#define BOT_MAXSENTRIESDISTANCE 1500.0

// for a bot to build at a location. Use higher values and bots will build sentries less close to other sentries on same team.
#define BOT_OBJECTIVEWAIT 10 // nr of seconds that must pass after a bot has built an objective related sentry until he can build such a sentry again.

#define SENTRY_TILT_TURRET EV_BYTE_controller2
#define SENTRY_TILT_LAUNCHER EV_BYTE_controller3
#define SENTRY_TILT_RADAR EV_BYTE_controller4
#define PEV_SENTRY_TILT_TURRET pev_controller_1
#define PEV_SENTRY_TILT_LAUNCHER pev_controller_2
#define PEV_SENTRY_TILT_RADAR pev_controller_3

#define STATUSINFOTIME 0.5 // the frequency of hud message updates when spectating a sentry, don't set too low or it could overflow clients. Data should now always send again as soon as it updates though.
#define SENTRY_RADAR 20 // use as high as possible but should still be working (ie be able to see sentries plotted on radar while in menu, too high values doesn't seem to work)
#define SENTRY_RADAR_TEAMBUILT 21 // same as above
#define SPYCAMTIME 5.0 // nr of seconds the spycam is active

enum OBJECTTYPE
{
OBJECT_GENERIC,
OBJECT_GRENADE,
OBJECT_PLAYER,
OBJECT_ARMOURY
}

// Global vars
new g_sentriesNum = 0
new g_sentries[MAXSENTRIES]
new g_playerSentries[32] = {0, ...}
new g_playerSentriesEdicts[32][MAXSENTRIESTOTAL]
new g_sModelIndexFireball, g_msgDamage, g_msgDeathMsg, g_msgScoreInfo, g_msgHostagePos,
g_msgHostageK, g_MAXPLAYERS

new Float:g_sentryOrigins[32][3]
new g_aimSentry[32]
new bool:g_inBuilding[32]
new bool:g_resetArmouryThisRound = true
new bool:g_hasArmouries = false
new Float:g_lastGameTime = 1.0 // dunno, looks like get_systime() is always 1.0 first time...
new Float:g_ONEEIGHTYTHROUGHPI, Float:g_gameTime, Float:g_deltaTime
new g_sentryStatusBuffer[32][256]
new g_sentryStatusTrigger
new g_selectedSentry[32] = {-1, ...}
new g_menuId // used to store index of menu
new g_lastObjectiveBuild[32], g_inSpyCam[32]

//For disabling building until some time passes after the new round
new bool:g_allowBuild //Building, upgrading and reparing is not allowed if this is false

#define PLUGIN "CSSB [WC3] Sentry Guns"
#define VERSION "1.1"
#define AUTHOR "CSSB"

new const szItemName[] = {"Сторожевая пушка"}

//Идентификаторы оружия
new iIdItemSentry;

//Переменные Cvar
new iCvarItemCost,iCvarSentryMax, iCvarSentryCost1, iCvarSentryCost2, iCvarSentryCost3, iCvarSentryTeam,iCvarSentryWait,iCvarOnOffItem;
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Встроенные функции--------------------BEGIN
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR);

//Команды
register_clcmd("say sentryguns","cmdBuyExtraItem", -1 );
register_clcmd("say /sentryguns","cmdBuyExtraItem", -1 );
register_clcmd("sentryguns", "cmdBuyExtraItem",-1);

//Регистрация переменных
iCvarItemCost = register_cvar("wc3_sentry_cost", "8000");
iCvarSentryMax = register_cvar("wc3_sentry_max", "2");
iCvarSentryCost1 = register_cvar("wc3_sentry_cost_level_1", "0");
iCvarSentryCost2 = register_cvar("wc3_sentry_cost_level_2", "2000");
iCvarSentryCost3 = register_cvar("wc3_sentry_cost_level_3", "3000");
iCvarSentryTeam = register_cvar("wc3_sentry_team", "2");
iCvarSentryWait = register_cvar("wc3_sentry_wait", "1.0");
iCvarOnOffItem = register_cvar("wc3_sentry_on_off", "1");

//FM Форварды
register_forward(FM_TraceLine, "fwTraceLinePost", 1);

//События
register_event("ResetHUD", "evNewRound", "b");
register_event("SendAudio", "evEndRound", "a", "2&%!MRAD_terwin", "2&%!MRAD_ctwin", "2&%!MRAD_rounddraw");
register_event("TextMsg", "evEndRound", "a", "2&#Game_C", "2&#Game_w");
register_event("TextMsg", "evEndRound", "a", "2&#Game_will_restart_in");
register_event( "TeamInfo", "evJoinTeam", "a");

//Регистрация предмета
iIdItemSentry = wc3_register_extra_item(szItemName, get_pcvar_num(iCvarItemCost),iCvarOnOffItem,1);

//Процедуры 'прикосновения'
if (find_ent_by_class(0, "func_bomb_target"))
{
register_touch("func_bomb_target", "player", "thPlayerReachedTarget")
register_touch("weaponbox", "player", "thPlayerWeaponBox")
}

if (find_ent_by_class(0, "func_hostage_rescue"))
register_touch("func_hostage_rescue", "player", "thPlayerReachedHostageRescue")

if (find_ent_by_class(0, "func_vip_safetyzone"))
register_touch("func_vip_safetyzone", "player", "thPlayerReachedTarget")

if (find_ent_by_class(0, "hostage_entity"))
register_touch("hostage_entity", "player", "thPlayerHostage")

register_touch("sentry", "player", "thPlayerSentry")

//Сообщения
register_message(23, "msgTempEntity") // <-- works for 0.16 as well

//Действия
register_think("sentrybase", "tnkSentryBase")

//Сообщения ID
g_msgDamage = get_user_msgid("Damage")
g_msgDeathMsg = get_user_msgid("DeathMsg")
g_msgScoreInfo = get_user_msgid("ScoreInfo")
g_msgHostagePos = get_user_msgid("HostagePos")
g_msgHostageK = get_user_msgid("HostageK")

g_MAXPLAYERS = get_global_int(GL_maxClients)
g_ONEEIGHTYTHROUGHPI = 180.0 / PI

// InitArmoury saves the location of all onground weapons. Later we restore them to these origins when a newround begin.
set_task(5.0, "InitArmoury")

//Загрузка файла конфигурации
new szConfigsDir[256];
get_configsdir(szConfigsDir, sizeof(szConfigsDir) - 1);
server_cmd("exec %s/CSSBConfigs/cssbWC3Items/wc3_sentry_guns.cfg", szConfigsDir);
}


public client_disconnect(id)
{
while (GetSentryCount(id) > 0)
sentry_detonate_by_owner(id)
}

public client_putinserver(id)
{
if (is_user_bot(id))
{
new parm[1]
parm[0] = id
botbuildsrandomly(parm)

}

return PLUGIN_CONTINUE
}

public plugin_modules()
{
require_module("engine")
require_module("fun")
require_module("cstrike")
require_module("fakemeta")
}

public plugin_precache()
{
precache_model("models/sentries/base.mdl")
precache_model("models/sentries/sentry1.mdl")
precache_model("models/sentries/sentry2.mdl")
precache_model("models/sentries/sentry3.mdl")
g_sModelIndexFireball = precache_model("sprites/zerogxplode.spr") // explosion
precache_sound("debris/bustmetal1.wav") // metal, computer breaking
precache_sound("debris/bustmetal2.wav") // metal, computer breaking
precache_sound("debris/metal1.wav") // metal breaking (needed for comp also?!)
precache_sound("debris/metal3.wav") // metal breaking (needed for comp also?!)
precache_model("models/computergibs.mdl") // computer breaking
precache_sound("sentries/asscan1.wav")
precache_sound("sentries/asscan2.wav")
precache_sound("sentries/asscan3.wav")
precache_sound("sentries/asscan4.wav")
precache_sound("sentries/turridle.wav")
precache_sound("sentries/turrset.wav")
precache_sound("sentries/turrspot.wav")
precache_sound("sentries/building.wav")
precache_sound("weapons/m249-1.wav")
}

//--------------------Встроенные функции--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Команды плагина--------------------BEGIN
//Команда покупки предмета
public cmdBuyExtraItem(idUser)
{
wc3_buy_extra_item(idUser, iIdItemSentry);
}
//--------------------Команды плагина--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Forwards--------------------BEGIN
public fwTraceLinePost(Float:start[3], Float:end[3], noMonsters, player)
{
if (is_user_bot(player) || player < 1 || player > g_MAXPLAYERS)
return FMRES_IGNORED

if (!is_user_alive(player))
return FMRES_IGNORED

SetStatusTrigger(player, false)

new hitEnt = get_tr(TR_pHit)
if (hitEnt <= g_MAXPLAYERS)
return FMRES_IGNORED

new classname[11], sentry = 0, base = 0
entity_get_string(hitEnt, EV_SZ_classname, classname, 10)
if (equal(classname, "sentrybase"))
{
base = hitEnt
sentry = entity_get_edict(hitEnt, BASE_ENT_SENTRY)
}
else if (equal(classname, "sentry"))
{
sentry = hitEnt
base = entity_get_edict(sentry, SENTRY_ENT_BASE)
}
if (!sentry || !base || entity_get_int(sentry, SENTRY_INT_FIRE) == SENTRY_FIREMODE_NUTS)
return FMRES_IGNORED
new Float:health = entity_get_float(sentry, EV_FL_health)

if (health <= 0)
return FMRES_IGNORED

new Float:basehealth = entity_get_float(base, EV_FL_health)

if (basehealth <= 0)
return FMRES_IGNORED

new team = entity_get_int(sentry, SENTRY_INT_TEAM)

if (team != get_user_team(player))
return FMRES_IGNORED

// Display health
new level = entity_get_int(sentry, SENTRY_INT_LEVEL)
new upgradeInfo[128]
if (PlayerCanUpgradeSentry(player, sentry))
format(upgradeInfo, charsmax(upgradeInfo), "%L",LANG_PLAYER,"WC3SHM_SG_UPGRADE_ME_LEVEL",
level + 2,
fCostSentryGuns(level + 1));

else if (level < SENTRY_LEVEL_3)
format(upgradeInfo, charsmax(upgradeInfo), "%L",LANG_PLAYER,"WC3SHM_SG_UPGRADE_COST", fCostSentryGuns(level + 1))
else
upgradeInfo = ""

new tempStatusBuffer[256]
format(tempStatusBuffer, charsmax(tempStatusBuffer), "%L",LANG_PLAYER,"WC3SHM_SG_DATA",
floatround(health),
floatround(g_HEALTHS[level]),
floatround(basehealth),
floatround(g_HEALTHS[0]),
level + 1, upgradeInfo);

SetStatusTrigger(player, true)
if (!task_exists(TASKID_SENTRYSTATUS + player) || !equal(tempStatusBuffer, g_sentryStatusBuffer[player - 1]))
{
// may still exist if !equal was true, so we remove previous task. This happens when sentry is being fired upon, player gets enough money to upgrade or sentry
// suddenly is upgradeable because another teammate upgraded it or something. This should make for instant updates to message without risking sending a lot of messages
// just in case data updated, now we only send more often if data changed often enough.
remove_task(TASKID_SENTRYSTATUS + player)

g_sentryStatusBuffer[player - 1] = tempStatusBuffer
new parms[2]
parms[0] = player
parms[1] = team
set_task(0.0, "displaysentrystatus", TASKID_SENTRYSTATUS + player, parms, 2)
}

return FMRES_IGNORED
}

// Counting level, team, money and DEFINES
bool:PlayerCanUpgradeSentry(player, sentry)
{
new level = entity_get_int(sentry, SENTRY_INT_LEVEL)
switch(level)
{
case SENTRY_LEVEL_1:
{
#if defined DISALLOW_OWN_UPGRADES
if (player == GetSentryPeople(sentry, OWNER))
return false
#endif

return get_user_team(player) == entity_get_int(sentry, SENTRY_INT_TEAM) && cs_get_user_money(player) >= fCostSentryGuns(level + 1)
}
case SENTRY_LEVEL_2:
{
#if defined DISALLOW_TWO_UPGRADES
if (player == GetSentryPeople(sentry, UPGRADER_1))
return false
#endif

return get_user_team(player) == entity_get_int(sentry, SENTRY_INT_TEAM) && cs_get_user_money(player) >= fCostSentryGuns(level + 1)
}
}
return false
}

//--------------------Forwards--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Вызов Natives--------------------BEGIN
//wc3_register_extra_item
public wc3_extra_item_selected(id, itemid)
{
if (itemid == iIdItemSentry)
{
createsentryhere(id);
}
}
//--------------------Вызов Natives--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------События--------------------BEGIN
//Когда игрок меняет команду (пушка взрывается)
public evJoinTeam()
{
//Get the id from the event data
new id = read_data(1)

//Remove sentries
while(GetSentryCount(id)>0)
sentry_detonate_by_owner(id, true)

return PLUGIN_CONTINUE
}

//Новый раунд
public evNewRound(id)
{
//Disallow building and enable it after some time
g_allowBuild= false
set_task(get_pcvar_float(iCvarSentryWait), "enablesentrybur")

g_inBuilding[id - 1] = false

#if !defined SENTRIES_SURVIVE_ROUNDS
while(GetSentryCount(id) > 0)
sentry_detonate_by_owner(id, true)
#endif

if (!g_resetArmouryThisRound && g_hasArmouries)
{
ResetArmoury()
g_resetArmouryThisRound = true
}

return PLUGIN_CONTINUE
}
//Конец раунда
public evEndRound()
{
if (!g_hasArmouries)
return PLUGIN_CONTINUE

set_task(4.0, "ResetArmouryFalse")

return PLUGIN_CONTINUE
}

//--------------------События--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Touch--------------------BEGIN
public thPlayerReachedTarget(target, bot)
{
if (!is_user_bot(bot) || GetSentryCount(bot) >= MAXPLAYERSENTRIES || entity_get_int(bot, EV_INT_bInDuck) || cs_get_user_vip(bot) || get_systime() < g_lastObjectiveBuild[bot - 1] + BOT_OBJECTIVEWAIT)
return PLUGIN_CONTINUE

BotBuild(bot)
g_lastObjectiveBuild[bot - 1] = get_systime()

return PLUGIN_CONTINUE
}


public thPlayerWeaponBox(weaponbox, bot)
{
if (!is_user_bot(bot) || GetSentryCount(bot) >= MAXPLAYERSENTRIES || cs_get_user_team(bot) != CS_TEAM_CT)
return PLUGIN_CONTINUE

new model[22]
entity_get_string(weaponbox, EV_SZ_model, model, 21)
if (!equal(model, "models/w_backpack.mdl"))
return PLUGIN_CONTINUE

// A ct will build near a dropped bomb
BotBuild(bot, 0.0, 2.0)

return PLUGIN_CONTINUE
}

public thPlayerReachedHostageRescue(target, bot)
{
if (!is_user_bot(bot) || GetSentryCount(bot) >= MAXPLAYERSENTRIES)
return PLUGIN_CONTINUE

// ~5% chance that a ct will build a sentry here, a t always builds
if (cs_get_user_team(bot) == CS_TEAM_CT)
{
if (random_num(0, 99) < 95)
return PLUGIN_CONTINUE
}

BotBuild(bot)

return PLUGIN_CONTINUE
}


public thPlayerHostage(hostage, bot)
{
if (!is_user_bot(bot) || GetSentryCount(bot) >= MAXPLAYERSENTRIES || cs_get_user_team(bot) != CS_TEAM_T)
return PLUGIN_CONTINUE

// Build a sentry close to a hostage
BotBuild(bot)

return PLUGIN_CONTINUE
}


public thPlayerSentry(sentry, player)
{
if (PlayerCanUpgradeSentry(player, sentry))
sentry_upgrade(player, sentry)

return PLUGIN_CONTINUE
}

//--------------------Touch--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Сообщения--------------------BEGIN
public msgTempEntity()
{
if (get_msg_args() != 15 && get_msg_arg_int(1) != TE_BREAKMODEL)
return PLUGIN_CONTINUE

// Something broke, maybe it was one of our sentries. Loop through all sentries to see if any of them has health <=0.
for (new i = 0; i < g_sentriesNum; i++)
{
if (entity_get_float(g_sentries[i], EV_FL_health) <= 0.0)
{
sentry_detonate(i, false, true)
i--
}
}

return PLUGIN_CONTINUE
}
//--------------------Сообщения--------------------END
//=============================================================================
//=============================================================================
//=============================================================================

//--------------------Think--------------------BEGIN
public tnkSentryBase(sentrybase)
{
sentrybase_broke(sentrybase)

return PLUGIN_CONTINUE
}
//--------------------Think--------------------END
//=============================================================================
//=============================================================================
//=============================================================================


//The function that enables building
public enablesentrybur()
{
g_allowBuild= true;
}

public createsentryhere(id)
{
//Check if the player is allowed to build
if(!g_allowBuild)
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_MUST_WAIT_UNTIL");

cssbColoredPrint(id, szMessage);

return PLUGIN_HANDLED
}

new sentry = AimingAtSentry(id, true)
// if a valid sentry
// if within range
// we can try to upgrade/repair...
if (sentry && entity_range(sentry, id) <= MAXUPGRADERANGE)
{
#if defined DISALLOW_OWN_UPGRADES
// Don't allow builder to upgrade his own sentry first time.
if (entity_get_int(sentry, SENTRY_INT_LEVEL) == SENTRY_LEVEL_1 && id == GetSentryPeople(sentry, OWNER))
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_UPGRADLVL_2");

cssbColoredPrint(id, szMessage);

return PLUGIN_HANDLED
}
#endif
#if defined DISALLOW_TWO_UPGRADES
// Don't allow upgrader to upgrade again.
if (entity_get_int(sentry, SENTRY_INT_LEVEL) == SENTRY_LEVEL_2 && id == GetSentryPeople(sentry, UPGRADER_1))
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_UPGRADLVL_3");

cssbColoredPrint(id, szMessage);

return PLUGIN_HANDLED
}
#endif
g_aimSentry[id - 1] = sentry
//if (entity_
sentry_upgrade(id, sentry)
}

else
{
sentry_build(id)
}
return PLUGIN_HANDLED
}

public sentry_build(id)
{
//Check if the player is allowed to build
if(!g_allowBuild)
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_MUST_WAIT_UNTIL");

cssbColoredPrint(id, szMessage);

return
}

if (GetSentryCount(id) >= MAXPLAYERSENTRIES)
{
// new wordnumbers[128]
// getnumbers(MAXPLAYERSENTRIES, wordnumbers, 127)
// new maxsentries = MAXPLAYERSENTRIES // stupid, but compiler gives warning on next line if a defined constant is used
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_NOBUILD",
get_pcvar_num(iCvarSentryMax));

cssbColoredPrint(id, szMessage);

return
}

else if (g_inBuilding[id - 1])
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_WOW");

cssbColoredPrint(id, szMessage);

return
}

else if (!is_user_alive(id))
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);
return;
}
/* else if (cs_get_user_money(id) < get_pcvar_num(iCvarItemCost))
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_EN_MONEY",
get_pcvar_num(iCvarItemCost));

cssbColoredPrint(id, szMessage);

return
}*/

else if (!entity_is_on_ground(id))
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_STAND_GROUND");

cssbColoredPrint(id, szMessage);

return
}
//else if (entity_get_int(id, EV_INT_flags) & FL_DUCKING)
//{

else if (entity_get_int(id, EV_INT_bInDuck))
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_YEAH_RIGHT");

cssbColoredPrint(id, szMessage);

return
}

else if ( get_pcvar_num( iCvarSentryTeam ) )
{
if( get_pcvar_num( iCvarSentryTeam ) < 0 && !is_user_admin(id) )
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_ADMINS_CAN_BUILD");

cssbColoredPrint(id, szMessage);

return
}
}

else if ( !(abs(get_pcvar_num( iCvarSentryTeam )) & _:cs_get_user_team(id)) )
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_TEAM_CANNOT_BUILD");

cssbColoredPrint(id, szMessage);
}


new Float:playerOrigin[3]
entity_get_vector(id, EV_VEC_origin, playerOrigin)

new Float:vNewOrigin[3]
new Float:vTraceDirection[3]
new Float:vTraceEnd[3]
new Float:vTraceResult[3]
velocity_by_aim(id, 64, vTraceDirection) // get a velocity in the directino player is aiming, with a multiplier of 64...
vTraceEnd[0] = vTraceDirection[0] + playerOrigin[0] // find the new max end position
vTraceEnd[1] = vTraceDirection[1] + playerOrigin[1]
vTraceEnd[2] = vTraceDirection[2] + playerOrigin[2]
trace_line(id, playerOrigin, vTraceEnd, vTraceResult) // trace, something can be in the way, use hitpoint from vTraceResult as new origin, if nothing's in the way it should be same as vTraceEnd
vNewOrigin[0] = vTraceResult[0] // just copy the new result position to new origin
vNewOrigin[1] = vTraceResult[1] // just copy the new result position to new origin
vNewOrigin[2] = playerOrigin[2] // always build in the same height as player.

if (!CreateSentryBase(vNewOrigin, id))
{
cs_set_user_money(id,cs_get_user_money(id) + get_pcvar_num(iCvarItemCost),0);
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_CANNOT_BUILD");

cssbColoredPrint(id, szMessage);
}
}

GetSentryCount(id)
{
return g_playerSentries[id - 1]
}

bool:GetStatusTrigger(player)
{
if (!is_user_alive(player))
return false

return g_sentryStatusTrigger & (1<<(player-1)) ? true : false
}

SetStatusTrigger(player, bool:onOrOff)
{
if (onOrOff)
g_sentryStatusTrigger |= (1<<(player - 1))
else
g_sentryStatusTrigger &= ~(1<<(player - 1))
}

IncreaseSentryCount(id, sentryEntity)
{
g_playerSentriesEdicts[id - 1][g_playerSentries[id - 1]] = sentryEntity
g_playerSentries[id - 1] = g_playerSentries[id - 1] + 1
new Float:sentryOrigin[3], iSentryOrigin[3]
entity_get_vector(sentryEntity, EV_VEC_origin, sentryOrigin)
FVecIVec(sentryOrigin, iSentryOrigin)

new name[32]
get_user_name(id, name, 31)
new CsTeams:builderTeam = cs_get_user_team(id)
for (new i = 1; i <= g_MAXPLAYERS; i++)
{
if (!is_user_connected(i) || !is_user_alive(i) || cs_get_user_team(i) != builderTeam || id == i)
continue

// format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",LANG_PLAYER,"WC3SHM_SG_CHATTAG",LANG_PLAYER,"WC3SHM_SG_HAS_BUILT_SENTRY",name,floatround(entity_range(i, sentryEntity)) );
// cssbColoredPrint(id, szMessage);

message_begin(MSG_ONE, g_msgHostagePos, {0,0,0}, i)
write_byte(i)
write_byte(SENTRY_RADAR_TEAMBUILT)
write_coord(iSentryOrigin[0])
write_coord(iSentryOrigin[1])
write_coord(iSentryOrigin[2])
message_end()

message_begin(MSG_ONE, g_msgHostageK, {0,0,0}, i)
write_byte(SENTRY_RADAR_TEAMBUILT)
message_end()
}

}

DecreaseSentryCount(id, sentry)
{
// Note that sentry does not exist at this moment, it's just an old index that should get zeroed where it occurs in g_playerSentriesEdicts[id - 1][]
g_selectedSentry[id - 1] = -1

for (new i = 0; i < g_playerSentries[id - 1]; i++)
{
if (g_playerSentriesEdicts[id - 1][i] == sentry)
{
// Copy last sentry edict index to this one
g_playerSentriesEdicts[id - 1][i] = g_playerSentriesEdicts[id - 1][g_playerSentries[id - 1] - 1]
// Zero out last sentry index
g_playerSentriesEdicts[id - 1][g_playerSentries[id - 1] - 1] = 0
break
}
}
g_playerSentries[id - 1] = g_playerSentries[id - 1] - 1
}

stock bool:CreateSentryBase(Float:origin[3], creator)
{
// Check contents of point, also trace lines from center to each of the eight ends
if (point_contents(origin) != CONTENTS_EMPTY || TraceCheckCollides(origin, 24.0))
{
return false
}

// Check that a trace from origin straight down to ground results in a distance which is the same as player height over ground?
new Float:hitPoint[3], Float:originDown[3]
originDown = origin
originDown[2] = -5000.0 // dunno the lowest possible height...
trace_line(0, origin, originDown, hitPoint)
new Float:baDistanceFromGround = vector_distance(origin, hitPoint)
new Float:difference = PLAYERORIGINHEIGHT - baDistanceFromGround
if (difference < -1 * HEIGHTDIFFERENCEALLOWED || difference > HEIGHTDIFFERENCEALLOWED)
return false

new entbase = create_entity("func_breakable") // func_wall
if (!entbase)
return false

// Set sentrybase health
new healthstring[16]
num_to_str(floatround(g_HEALTHS[0]), healthstring, 15)
DispatchKeyValue(entbase, "health", healthstring)
DispatchKeyValue(entbase, "material", "6")

DispatchSpawn(entbase)
// Change classname
entity_set_string(entbase, EV_SZ_classname, "sentrybase")
// Set model
entity_set_model(entbase, "models/sentries/base.mdl") // later set according to level
// Set size
new Float:mins[3], Float:maxs[3]
mins[0] = -16.0
mins[1] = -16.0
mins[2] = 0.0
maxs[0] = 16.0
maxs[1] = 16.0
maxs[2] = 1000.0 // Set to 16.0 later.
entity_set_size(entbase, mins, maxs)

// Set origin
entity_set_origin(entbase, origin)
// Set solidness
entity_set_int(entbase, EV_INT_solid, SOLID_SLIDEBOX) // SOLID_SLIDEBOX
// Set movetype
entity_set_int(entbase, EV_INT_movetype, MOVETYPE_TOSS) // head flies, base falls
// Set team
entity_set_int(entbase, BASE_INT_TEAM, get_user_team(creator))

new parms[2]
parms[0] = entbase
parms[1] = creator

g_sentryOrigins[creator - 1] = origin

emit_sound(creator, CHAN_AUTO, "sentries/building.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

set_task(BASESENTRYDELAY, "createsentryhead", 0, parms, 2)
g_inBuilding[creator - 1] = true

return true
}

public createsentryhead(parms[2])
{
new entbase = parms[0]

new creator = parms[1]

if (!g_inBuilding[creator - 1])
{
// g_inBuilding is reset upon new round, then don't continue with building sentry head. Remove base and return.
if (is_valid_ent(entbase))
remove_entity(entbase)
return
}

new Float:origin[3]
origin = g_sentryOrigins[creator - 1]

new ent = create_entity("func_breakable")

if (!ent)
{
if (is_valid_ent(entbase))
remove_entity(entbase)
return
}

new Float:mins[3], Float:maxs[3]
// Set true size of base... if it exists!
// Also set sentry <-> base connections, if base still exists
if (is_valid_ent(entbase))
{
mins[0] = -16.0
mins[1] = -16.0
mins[2] = 0.0
maxs[0] = 16.0
maxs[1] = 16.0
maxs[2] = 16.0
entity_set_size(entbase, mins, maxs)

entity_set_edict(ent, SENTRY_ENT_BASE, entbase)
entity_set_edict(entbase, BASE_ENT_SENTRY, ent)
}

// Store our sentry in array
g_sentries[g_sentriesNum] = ent

new healthstring[16]
num_to_str(floatround(g_HEALTHS[0]), healthstring, 15)
DispatchKeyValue(ent, "health", healthstring)
DispatchKeyValue(ent, "material", "6")

DispatchSpawn(ent)
// Change classname
entity_set_string(ent, EV_SZ_classname, "sentry")
// Set model
entity_set_model(ent, "models/sentries/sentry1.mdl") // later set according to level
// Set size
mins[0] = -16.0
mins[1] = -16.0
mins[2] = 0.0
maxs[0] = 16.0
maxs[1] = 16.0
maxs[2] = 48.0
entity_set_size(ent, mins, maxs)
// Set origin
entity_set_origin(ent, origin)
// Set starting angle
entity_get_vector(creator, EV_VEC_angles, origin)
origin[0] = 0.0
origin[1] += 180.0
entity_set_float(ent, SENTRY_FL_ANGLE, origin[1])
origin[2] = 0.0
entity_set_vector(ent, EV_VEC_angles, origin)
// Set solidness
entity_set_int(ent, EV_INT_solid, SOLID_SLIDEBOX) // SOLID_SLIDEBOX
// Set movetype
entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) // head flies, base doesn't
// Set tilt of cannon
set_pev(ent, PEV_SENTRY_TILT_TURRET, 127) //entity_set_byte(ent, SENTRY_TILT_TURRET, 127) // 127 is horisontal
// Tilt of rocket launcher barrels at level 3
set_pev(ent, PEV_SENTRY_TILT_LAUNCHER, 127) //entity_set_byte(ent, SENTRY_TILT_LAUNCHER, 127) // 127 is horisontal
// Angle of small radar at level 3
entity_set_float(ent, SENTRY_FL_RADARANGLE, 127.0)
set_pev(ent, PEV_SENTRY_TILT_RADAR, 127) //entity_set_byte(ent, SENTRY_TILT_RADAR, 127) // 127 is middle


// Set owner
//entity_set_edict(ent, SENTRY_ENT_OWNER, creator)
SetSentryPeople(ent, OWNER, creator)

// Set team
entity_set_int(ent, SENTRY_INT_TEAM, get_user_team(creator))

// Set level (not really necessary, but for looks)
entity_set_int(ent, SENTRY_INT_LEVEL, SENTRY_LEVEL_1)

// Top color
#if defined RANDOM_TOPCOLOR
new topColor = random_num(0, 255)
#else
new topColor = cs_get_user_team(creator) == CS_TEAM_CT ? COLOR_TOP_CT : COLOR_TOP_T
#endif
// Bottom color
#if defined RANDOM_BOTTOMCOLOR
new bottomColor = random_num(0, 255)
#else
new bottomColor = cs_get_user_team(creator) == CS_TEAM_CT ? COLOR_BOTTOM_CT : COLOR_BOTTOM_T
#endif

// Set color
new map = topColor | (bottomColor<<8)
entity_set_int(ent, EV_INT_colormap, map)

g_sentriesNum++

emit_sound(ent, CHAN_AUTO, "sentries/turrset.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

IncreaseSentryCount(creator, ent)

new parm[4]
parm[0] = ent
set_task(g_THINKFREQUENCIES[0], "sentry_think", TASKID_THINK + parm[0], parm, 1)

parm[1] = random_num(0, 1)
parm[2] = 0
parm[3] = 0
new directions = (random_num(0, 1)<<SENTRY_DIR_CANNON) | (random_num(0, 1)<<SENTRY_DIR_RADAR)
entity_set_int(ent, SENTRY_INT_PENDDIR, directions)

g_inBuilding[creator - 1] = false;

if (!is_valid_ent(entbase))
entity_set_int(ent, SENTRY_INT_FIRE, SENTRY_FIREMODE_NUTS);
}

public server_frame()
{
g_gameTime = get_gametime()
g_deltaTime = g_gameTime - g_lastGameTime

new tempSentries[MAXSENTRIES], Float:angles[3]

new tempSentriesNum = 0

for (new i = 0; i < g_sentriesNum; i++)
{
tempSentries[i] = g_sentries[i]
tempSentriesNum++
}

for (new i = 0; i < tempSentriesNum; i++)
{
sentry_pendulum(tempSentries[i], g_deltaTime)

if (entity_get_edict(tempSentries[i], SENTRY_ENT_SPYCAM) != 0)
{
entity_get_vector(tempSentries[i], EV_VEC_angles, angles)
entity_set_vector(entity_get_edict(tempSentries[i], SENTRY_ENT_SPYCAM), EV_VEC_angles, angles)
}
}

g_lastGameTime = g_gameTime
return PLUGIN_CONTINUE
}

sentry_pendulum(sentry, Float:deltaTime)
{
switch (entity_get_int(sentry, SENTRY_INT_FIRE))
{
case SENTRY_FIREMODE_NO:
{
new Float:angles[3]
entity_get_vector(sentry, EV_VEC_angles, angles)
new Float:baseAngle = entity_get_float(sentry, SENTRY_FL_ANGLE)
new directions = entity_get_int(sentry, SENTRY_INT_PENDDIR)

if (directions & (1<<SENTRY_DIR_CANNON))
{
angles[1] -= (PENDULUM_INCREMENT * deltaTime)// PENDULUM_INCREMENT get_cvar_float("pend_inc")

if (angles[1] < baseAngle - PENDULUM_MAX)
{
angles[1] = baseAngle - PENDULUM_MAX
directions &= ~(1<<SENTRY_DIR_CANNON)
entity_set_int(sentry, SENTRY_INT_PENDDIR, directions)
}
}

else
{
angles[1] += (PENDULUM_INCREMENT * deltaTime)// PENDULUM_INCREMENT get_cvar_float("pend_inc")

if (angles[1] > baseAngle + PENDULUM_MAX)
{
angles[1] = baseAngle + PENDULUM_MAX
directions |= (1<<SENTRY_DIR_CANNON)
entity_set_int(sentry, SENTRY_INT_PENDDIR, directions)
}
}

entity_set_vector(sentry, EV_VEC_angles, angles);

if (entity_get_int(sentry, SENTRY_INT_LEVEL) == SENTRY_LEVEL_3)
{
new Float:radarAngle = entity_get_float(sentry, SENTRY_FL_RADARANGLE)

if (directions & (1<<SENTRY_DIR_RADAR))
{
radarAngle = radarAngle - RADAR_INCREMENT// get_cvar_float("radar_increment")

if (radarAngle < 0.0)
{
radarAngle = 0.0
directions &= ~(1<<SENTRY_DIR_RADAR)
entity_set_int(sentry, SENTRY_INT_PENDDIR, directions)
}
}

else
{
radarAngle = radarAngle + RADAR_INCREMENT // get_cvar_float("radar_increment")

if (radarAngle > 255.0)
{
radarAngle = 255.0
directions |= (1<<SENTRY_DIR_RADAR)
entity_set_int(sentry, SENTRY_INT_PENDDIR, directions)
}
}
entity_set_float(sentry, SENTRY_FL_RADARANGLE, radarAngle)
set_pev(sentry, PEV_SENTRY_TILT_RADAR, floatround(radarAngle)) //entity_set_byte(sentry, SENTRY_TILT_RADAR, floatround(radarAngle))
}
return
}
case SENTRY_FIREMODE_NUTS:
{
new Float:angles[3]
entity_get_vector(sentry, EV_VEC_angles, angles)

new Float:spinSpeed = entity_get_float(sentry, SENTRY_FL_SPINSPEED)

if (entity_get_int(sentry, SENTRY_INT_PENDDIR) & (1<<SENTRY_DIR_CANNON))
{
angles[1] -= (spinSpeed * deltaTime)

if (angles[1] < 0.0)
{
angles[1] = 360.0 + angles[1]
}
}

else
{
angles[1] += (spinSpeed * deltaTime)

if (angles[1] > 360.0)
{
angles[1] = angles[1] - 360.0
}
}
// Increment speed raise
entity_set_float(sentry, SENTRY_FL_SPINSPEED, (spinSpeed += random_float(1.0, 2.0)))

new Float:maxSpin = entity_get_float(sentry, SENTRY_FL_MAXSPIN)

if (maxSpin == 0.0)
{
// Set rotation speed to explode at
entity_set_float(sentry, SENTRY_FL_MAXSPIN, maxSpin = random_float(500.0, 750.0))
}

else if (spinSpeed >= maxSpin)
{
sentry_detonate(sentry, false, false)
return
}
entity_set_vector(sentry, EV_VEC_angles, angles);

return
}
}
}

// Checks the contents of eight points corresponding to the bbox around ent origin. Also does a trace from origin to each point. If anything goes wrong, report a hit.
// TODO: high bounds should get higher, so that building in tight places not gets sentries stuck in roof... TraceCheckCollides
bool:TraceCheckCollides(Float:origin[3], const Float:BOUNDS)
{
new Float:traceEnds[8][3], Float:traceHit[3], hitEnt

// x, z, y
traceEnds[0][0] = origin[0] - BOUNDS
traceEnds[0][1] = origin[1] - BOUNDS
traceEnds[0][2] = origin[2] - BOUNDS

traceEnds[1][0] = origin[0] - BOUNDS
traceEnds[1][1] = origin[1] - BOUNDS
traceEnds[1][2] = origin[2] + BOUNDS

traceEnds[2][0] = origin[0] + BOUNDS
traceEnds[2][1] = origin[1] - BOUNDS
traceEnds[2][2] = origin[2] + BOUNDS

traceEnds[3][0] = origin[0] + BOUNDS
traceEnds[3][1] = origin[1] - BOUNDS
traceEnds[3][2] = origin[2] - BOUNDS
//
traceEnds[4][0] = origin[0] - BOUNDS
traceEnds[4][1] = origin[1] + BOUNDS
traceEnds[4][2] = origin[2] - BOUNDS

traceEnds[5][0] = origin[0] - BOUNDS
traceEnds[5][1] = origin[1] + BOUNDS
traceEnds[5][2] = origin[2] + BOUNDS

traceEnds[6][0] = origin[0] + BOUNDS
traceEnds[6][1] = origin[1] + BOUNDS
traceEnds[6][2] = origin[2] + BOUNDS

traceEnds[7][0] = origin[0] + BOUNDS
traceEnds[7][1] = origin[1] + BOUNDS
traceEnds[7][2] = origin[2] - BOUNDS

for (new i = 0; i < 8; i++)
{
if (point_contents(traceEnds[i]) != CONTENTS_EMPTY)
return true

hitEnt = trace_line(0, origin, traceEnds[i], traceHit)

if (hitEnt != 0)
return true

for (new j = 0; j < 3; j++)
{
if (traceEnds[i][j] != traceHit[j])
return true
}
}

return false
}


//#define TE_TRACER 6 // tracer effect from point to point
// coord, coord, coord (start)
// coord, coord, coord (end)

tracer(Float:start[3], Float:end[3])
{
//new start_[3]
new start_[3], end_[3]
FVecIVec(start, start_)
FVecIVec(end, end_)
message_begin(MSG_BROADCAST, SVC_TEMPENTITY) // MSG_PAS MSG_BROADCAST
write_byte(TE_TRACER)
write_coord(start_[0])
write_coord(start_[1])
write_coord(start_[2])
write_coord(end_[0])
write_coord(end_[1])
write_coord(end_[2])
message_end()
}

stock create_explosion(Float:origin_[3])
{
new origin[3]
FVecIVec(origin_, origin)

message_begin(MSG_BROADCAST, SVC_TEMPENTITY, origin) // MSG_PAS not really good here
write_byte(TE_EXPLOSION)
write_coord(origin[0])
write_coord(origin[1])
write_coord(origin[2])
write_short(g_sModelIndexFireball)
write_byte(random_num(0, 20) + 50) // scale * 10 // random_num(0, 20) + 20
write_byte(12) // framerate
write_byte(TE_EXPLFLAG_NONE)
message_end()

// Blast stuff away
genericShock(origin_, SENTRYEXPLODERADIUS, "weaponbox", 32, SENTRYSHOCKPOWER, OBJECT_GENERIC)
genericShock(origin_, SENTRYEXPLODERADIUS, "armoury_entity", 32, SENTRYSHOCKPOWER, OBJECT_ARMOURY)
genericShock(origin_, SENTRYEXPLODERADIUS, "player", 32, SENTRYSHOCKPOWER, OBJECT_PLAYER)
genericShock(origin_, SENTRYEXPLODERADIUS, "grenade", 32, SENTRYSHOCKPOWER, OBJECT_GRENADE)
genericShock(origin_, SENTRYEXPLODERADIUS, "hostage_entity", 32, SENTRYSHOCKPOWER, OBJECT_GENERIC)

// Hurt ppl in vicinity
new Float:playerOrigin[3], Float:distance, Float:flDmgToDo, Float:dmgbase = DMG_EXPLOSION_TAKE + 0.0, newHealth
for (new i = 1; i <= g_MAXPLAYERS; i++)
{
if (!is_user_alive(i))
continue

entity_get_vector(i, EV_VEC_origin, playerOrigin)
distance = vector_distance(playerOrigin, origin_)

if (distance <= SENTRYEXPLODERADIUS)
{
flDmgToDo = dmgbase - (dmgbase * (distance / SENTRYEXPLODERADIUS))
newHealth = get_user_health(i) - floatround(flDmgToDo)

if (newHealth <= 0)
{
set_task(0.0, "TicketToHell", i)
continue
}

set_user_health(i, newHealth)

message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, {0,0,0}, i)
write_byte(floatround(flDmgToDo))
write_byte(floatround(flDmgToDo))
write_long(DMG_BLAST)
write_coord(origin[0])
write_coord(origin[1])
write_coord(origin[2])
message_end()
}
}
}

// Hacks, damn you!
public TicketToHell(player)
{
if (!is_user_connected(player))
return

new frags = get_user_frags(player)
user_kill(player, 1) // don't decrease frags
new parms[4]
parms[0] = player
parms[1] = frags
parms[2] = cs_get_user_deaths(player)
parms[3] = int:cs_get_user_team(player)
set_task(0.0, "DelayedScoreInfoUpdate", 0, parms, 4)
}

public DelayedScoreInfoUpdate(parms[4])
{
scoreinfo_update(parms[0], parms[1], parms[2], parms[3])
}

stock genericShock(Float:hitPointOrigin[3], Float:radius, classString[], maxEntsToFind, Float:power, OBJECTTYPE:objecttype)
{
new entList[32]
if (maxEntsToFind > 32)
maxEntsToFind = 32

new entsFound = find_sphere_class(0, classString, radius, entList, maxEntsToFind, hitPointOrigin)

new Float:entOrigin[3]
new Float:velocity[3]
new Float:cOrigin[3]

for (new j = 0; j < entsFound; j++)
{
switch (objecttype)
{
case OBJECT_PLAYER:
{
if (!is_user_alive(entList[j]))// Don't move dead players
continue
}

case OBJECT_GRENADE:
{
new l_model[16]
entity_get_string(entList[j], EV_SZ_model, l_model, 15)

if (equal(l_model, "models/w_c4.mdl")) // don't move planted c4s :-P
continue
}
}
entity_get_vector(entList[j], EV_VEC_origin, entOrigin) // get_entity_origin(entList[j],entOrigin)

new Float:distanceNadePl = vector_distance(entOrigin, hitPointOrigin)

// Stuff on ground AND below explosion are "placed" a distance above explosion Y-wise ([2]), so that they fly off ground etc.
if (entity_is_on_ground(entList[j]) && entOrigin[2] < hitPointOrigin[2])
entOrigin[2] = hitPointOrigin[2] + distanceNadePl

entity_get_vector(entList[j], EV_VEC_velocity, velocity)

cOrigin[0] = (entOrigin[0] - hitPointOrigin[0]) * radius / distanceNadePl + hitPointOrigin[0]
cOrigin[1] = (entOrigin[1] - hitPointOrigin[1]) * radius / distanceNadePl + hitPointOrigin[1]
cOrigin[2] = (entOrigin[2] - hitPointOrigin[2]) * radius / distanceNadePl + hitPointOrigin[2]

velocity[0] += (cOrigin[0] - entOrigin[0]) * power
velocity[1] += (cOrigin[1] - entOrigin[1]) * power
velocity[2] += (cOrigin[2] - entOrigin[2]) * power

entity_set_vector(entList[j], EV_VEC_velocity, velocity)

}
}

stock entity_is_on_ground(entity)
{
return entity_get_int(entity, EV_INT_flags) & FL_ONGROUND
}

sentrybase_broke(sentrybase)
{
new sentry = entity_get_edict(sentrybase, BASE_ENT_SENTRY)
if (is_valid_ent(sentrybase))
remove_entity(sentrybase)

// Sentry could be 0 which should mean it has not been built yet. No need to do anything in that case.
if (sentry == 0)
return

entity_set_int(sentry, SENTRY_INT_FIRE, SENTRY_FIREMODE_NUTS)
// Set cannon tower straight, calculate tower tilt offset to angles later... entityviewhitpoint fn needs changing for this to use a custom angle vector
set_pev(sentry, PEV_SENTRY_TILT_TURRET, 127)//entity_set_byte(sentry, SENTRY_TILT_TURRET, 127)
}

sentry_detonate(sentry, bool:quiet, bool:isIndex)
{
// Explode!
new i

if (isIndex)
{
i = sentry
sentry = g_sentries[sentry]
if (!is_valid_ent(sentry))
return
}

else
{
if (!is_valid_ent(sentry))
return
// Find index of this sentry
for (new j = 0; j < g_sentriesNum; j++)
{
if (g_sentries[j] == sentry)
{
i = j
break
}
}
}

// Kill tasks
remove_task(TASKID_THINK + sentry) // removes think
remove_task(TASKID_THINKPENDULUM + sentry) // removes think
remove_task(TASKID_SENTRYONRADAR + sentry) // in case someone's displaying this on radar

new owner = GetSentryPeople(sentry, OWNER)

// If sentry has a spycam, call the stuff to remove it now
if (entity_get_edict(sentry, SENTRY_ENT_SPYCAM) != 0)
{
remove_task(TASKID_SPYCAM + owner) // remove the ongoing task...
// And call this now on our own...
new parms[3]
parms[0] = owner
parms[1] = entity_get_edict(sentry, SENTRY_ENT_SPYCAM)
parms[2] = sentry
DestroySpyCam(parms)
}

if (!quiet)
{
#if defined EXPLODINGSENTRIES
new Float:origin[3]
entity_get_vector(sentry, EV_VEC_origin, origin)
create_explosion(origin)
#endif

// Report to owner that it broke
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_SENTRY_GUN_DETONATED");

cssbColoredPrint(owner, szMessage);
}
DecreaseSentryCount(owner, sentry)
//SetHasSentry(GetSentryPeople(sentry, OWNER), false)

// Remove base first
if (entity_get_int(sentry, SENTRY_INT_FIRE) != SENTRY_FIREMODE_NUTS)
set_task(0.0, "delayedremovalofentity", entity_get_edict(sentry, SENTRY_ENT_BASE))
// Remove this entity
set_task(0.0, "delayedremovalofentity", sentry)
// Put the last sentry in the deleted entity's place
g_sentries[i] = g_sentries[g_sentriesNum - 1]
// Lower nr of sentries
g_sentriesNum--
}

public delayedremovalofentity(entity)
{
if (!is_valid_ent(entity))
return;

remove_entity(entity);
}

sentry_detonate_by_owner(owner, bool:quiet = false)
{
for(new i = 0; i < g_sentriesNum; i++)
{
if (GetSentryPeople(g_sentries[i], OWNER) == owner)
{
sentry_detonate(i, quiet, true)
break
}
}
}

public sentry_think(parm[1])
{
if (!is_valid_ent(parm[0]))
return;

new ent = parm[0]

new Float:sentryOrigin[3], Float:hitOrigin[3], hitent
entity_get_vector(ent, EV_VEC_origin, sentryOrigin)
sentryOrigin[2] += CANNONHEIGHTFROMFEET // Move up some, this should be the Y origin of the cannon

// If fire, do a trace and fire
new firemode = entity_get_int(ent, SENTRY_INT_FIRE)

new target = entity_get_edict(ent, SENTRY_ENT_TARGET)
//if (firemode == SENTRY_FIREMODE_YES && is_valid_ent(target) && zp_get_user_zombie(target) != entity_get_int(ent, SENTRY_INT_TEAM))
if (firemode == SENTRY_FIREMODE_YES && is_valid_ent(target))
{ // temp removed team check: && get_user_team(target) != entity_get_int(ent, SENTRY_INT_TEAM)
new sentryLevel = entity_get_int(ent, SENTRY_INT_LEVEL)

// Is target still visible?
new Float:targetOrigin[3]
entity_get_vector(target, EV_VEC_origin, targetOrigin)

// Adjust for ducking. This is still not 100%. :-(
if (entity_get_int(target, EV_INT_flags) & FL_DUCKING)
targetOrigin[2] += TARGETUPMODIFIER

hitent = trace_line(ent, sentryOrigin, targetOrigin, hitOrigin)
if (hitent == entity_get_edict(ent, SENTRY_ENT_BASE))
hitent = trace_line(hitent, hitOrigin, targetOrigin, hitOrigin)

if (hitent != target && is_user_alive(hitent))
{
// Another new enemy target got into scope, pick this new enemy as a new target...
target = hitent
entity_set_edict(ent, SENTRY_ENT_TARGET, hitent)
}

if (hitent == target)
{
// Fire here
sentry_turntotarget(ent, sentryOrigin, target, targetOrigin)
// Firing sound
emit_sound(ent, CHAN_WEAPON, "weapons/m249-1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

new Float:hitRatio = random_float(0.0, 1.0) - g_HITRATIOS[sentryLevel] // ie 0.5 - 0.7 = -0.2, a hit and 0.8 - 0.7 = a miss by 0.1

if (!get_user_godmode(target) && hitRatio <= 0.0)
{
sentry_damagetoplayer(ent, sentryLevel, sentryOrigin, target)
}
else
{
// Tracer hitOrigin adjusted for miss...
new Float:sentryAngle[3] = {0.0, 0.0, 0.0}

new Float:x = hitOrigin[0] - sentryOrigin[0]
new Float:z = hitOrigin[1] - sentryOrigin[1]
new Float:radians = floatatan(z/x, radian)
sentryAngle[1] = radians * g_ONEEIGHTYTHROUGHPI

if (hitOrigin[0] < sentryOrigin[0])
sentryAngle[1] -= 180.0

new Float:h = hitOrigin[2] - sentryOrigin[2]
new Float:b = vector_distance(sentryOrigin, hitOrigin)
radians = floatatan(h/b, radian)
sentryAngle[0] = radians * g_ONEEIGHTYTHROUGHPI;

sentryAngle[0] += random_float(-10.0 * hitRatio, 10.0 * hitRatio) // aim is a little off here :-)
sentryAngle[1] += random_float(-10.0 * hitRatio, 10.0 * hitRatio) // aim is a little off here :-)
engfunc(EngFunc_MakeVectors, sentryAngle)
new Float:vector[3]
get_global_vector(GL_v_forward, vector)
for (new i = 0; i < 3; i++)
vector[i] *= 1000;

new Float:traceEnd[3]
for (new i = 0; i < 3; i++)
traceEnd[i] = vector[i] + sentryOrigin[i]

new hitEnt = ent
while((hitEnt = trace_line(hitEnt, hitOrigin, traceEnd, hitOrigin)))
{
// continue tracing until hit nothing...
}


}
tracer(sentryOrigin, hitOrigin)

// Don't do any more here
set_task(THINKFIREFREQUENCY, "sentry_think", TASKID_THINK + parm[0], parm, 1)
return
}
else
{
// Else target isn't still visible, unset fire state.
entity_set_int(ent, SENTRY_INT_FIRE, SENTRY_FIREMODE_NO)
// Don't return here, continue with searching for targets below...
}
}

else if (firemode == SENTRY_FIREMODE_NUTS)
{
new hitEnt = entityviewhitpoint(ent, sentryOrigin, hitOrigin)
// Firing sound
emit_sound(ent, CHAN_WEAPON, "weapons/m249-1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
// Tracer effect
tracer(sentryOrigin, hitOrigin)

if (is_user_connected(hitEnt) && is_user_alive(hitEnt))
{
// Do damage to player
sentry_damagetoplayer(ent, entity_get_int(ent, SENTRY_INT_LEVEL), sentryOrigin, hitEnt)
}

// Don't do any more here
set_task(THINKFIREFREQUENCY, "sentry_think", TASKID_THINK + parm[0], parm, 1)
return
}

// Tell what players you see
if (random_num(0, 99) < 10)
emit_sound(ent, CHAN_AUTO, "sentries/turridle.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

new closestTarget = 0, Float:closestDistance, Float:distance, Float:closestOrigin[3], Float:playerOrigin[3], sentryTeam = entity_get_int(ent, SENTRY_INT_TEAM)
for (new i = 1; i <= g_MAXPLAYERS; i++)
{
if (!is_user_connected(i) || !is_user_alive(i) || get_user_team(i) == sentryTeam) // temporarily dont check team: || get_user_team(i) == sentryTeam
continue

entity_get_vector(i, EV_VEC_origin, playerOrigin)

// Adjust for ducking. This is still not 100%. :-(
if (entity_get_int(i, EV_INT_flags) & FL_DUCKING)
playerOrigin[2] += TARGETUPMODIFIER

hitent = trace_line(ent, sentryOrigin, playerOrigin, hitOrigin)

if (hitent == entity_get_edict(ent, SENTRY_ENT_BASE))
{
// We traced into our base, do another trace from there
hitent = trace_line(hitent, hitOrigin, playerOrigin, hitOrigin)
}

if (hitent == i)
{
distance = vector_distance(sentryOrigin, playerOrigin)
closestOrigin = playerOrigin

if (distance < closestDistance || closestTarget == 0)
{
closestTarget = i
closestDistance = distance
}
}
}

if (closestTarget)
{
// We found a target, play sound and turn to target
emit_sound(ent, CHAN_AUTO, "sentries/turrspot.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
sentry_turntotarget(ent, sentryOrigin, closestTarget, closestOrigin)

// Set to fire mode and set target (always set also a new target when setting fire mode 1!!!)
entity_set_int(ent, SENTRY_INT_FIRE, SENTRY_FIREMODE_YES)
entity_set_edict(ent, SENTRY_ENT_TARGET, closestTarget)
// Set radar straight...
entity_set_float(ent, SENTRY_FL_RADARANGLE, 127.0)
set_pev(ent, PEV_SENTRY_TILT_RADAR, 127)
}

else
entity_set_int(ent, SENTRY_INT_FIRE, SENTRY_FIREMODE_NO)

set_task(g_THINKFREQUENCIES[entity_get_int(ent, SENTRY_INT_LEVEL)], "sentry_think", TASKID_THINK + parm[0], parm, 1)
}

stock sentry_damagetoplayer(sentry, sentryLevel, Float:sentryOrigin[3], target)
{
new newHealth = get_user_health(target) - g_DMG[sentryLevel]

if (newHealth <= 0)
{
new targetFrags = get_user_frags(target) + 1
new owner = GetSentryPeople(sentry, OWNER)
new ownerFrags = get_user_frags(owner) + 1
set_user_frags(target, targetFrags) // otherwise frags are subtracted from victim for dying (!!)
set_user_frags(owner, ownerFrags)
// Give money to player here
new contributors[3], moneyRewards[33] = {0, ...}
contributors[0] = owner
contributors[1] = GetSentryPeople(sentry, UPGRADER_1)
contributors[2] = GetSentryPeople(sentry, UPGRADER_2)
for (new i = SENTRY_LEVEL_1; i <= sentryLevel; i++)
{
moneyRewards[contributors[i]] += g_SENTRYFRAGREWARDS[i]
}

for (new i = 1; i <= g_MAXPLAYERS; i++)
{
if (moneyRewards[i] && is_user_connected(i) )
{
cs_set_user_money(i, cs_get_user_money(i) + moneyRewards[i])
}
}

message_begin(MSG_ALL, g_msgDeathMsg, {0, 0, 0} ,0)
write_byte(owner)
write_byte(target)
write_byte(0)
write_string("sentry gun")
message_end()

scoreinfo_update(owner, ownerFrags, cs_get_user_deaths(owner), int:cs_get_user_team(owner))

set_msg_block(g_msgDeathMsg, BLOCK_ONCE)
}

set_user_health(target, newHealth)

message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, {0,0,0}, target) //
write_byte(g_DMG[sentryLevel]) // write_byte(DMG_SAVE)
write_byte(g_DMG[sentryLevel])
write_long(DMG_BULLET)
write_coord(floatround(sentryOrigin[0]))
write_coord(floatround(sentryOrigin[1]))
write_coord(floatround(sentryOrigin[2]))
message_end()
}

scoreinfo_update(id, frags, deaths, team)
{
// Send msg to update ppls scoreboards.
message_begin(MSG_ALL, g_msgScoreInfo)
write_byte(id)
write_short(frags)
write_short(deaths)
write_short(0)
write_short(team)
message_end()
}

sentry_turntotarget(ent, Float:sentryOrigin[3], target, Float:closestOrigin[3])
{
if (target)
{
new name[32]
get_user_name(target, name, 31)

// Alter ent's angle
new Float:newAngle[3]
entity_get_vector(ent, EV_VEC_angles, newAngle)
new Float:x = closestOrigin[0] - sentryOrigin[0]
new Float:z = closestOrigin[1] - sentryOrigin[1]
new Float:radians = floatatan(z/x, radian)
newAngle[1] = radians * g_ONEEIGHTYTHROUGHPI
if (closestOrigin[0] < sentryOrigin[0])

newAngle[1] -= 180.0

entity_set_float(ent, SENTRY_FL_ANGLE, newAngle[1])
// Tilt is handled thorugh the EV_BYTE_controller1 member. 0-255 are the values, 127ish should be horisontal aim, 255 is furthest down (about 50 degrees off)
// and 0 is also about 50 degrees up. Scope = ~100 degrees

// Set tilt
new Float:h = closestOrigin[2] - sentryOrigin[2]
new Float:b = vector_distance(sentryOrigin, closestOrigin)
radians = floatatan(h/b, radian)
new Float:degs = radians * g_ONEEIGHTYTHROUGHPI;
// Now adjust EV_BYTE_controller1
// Each degree corresponds to about 100/256 "bytes", = ~0,39 byte / degree (ok this is not entirely true, just tweaked for now with SENTRYTILTRADIUS)
new Float:RADIUS = SENTRYTILTRADIUS // get_cvar_float("sentry_tiltradius");
new Float:degreeByte = RADIUS/256.0; // tweak radius later
new Float:tilt = 127.0 - degreeByte * degs; // 127 is center of 256... well, almost
set_pev(ent, PEV_SENTRY_TILT_TURRET, floatround(tilt)) //entity_set_byte(ent, SENTRY_TILT_TURRET, floatround(tilt))
entity_set_vector(ent, EV_VEC_angles, newAngle)
}

}

AimingAtSentry(id, bool:alwaysReturn = false)
{
new hitEnt, bodyPart
if (get_user_aiming(id, hitEnt, bodyPart) == 0.0)
return 0

new sentry = 0
while (hitEnt)
{
new classname[32], l_sentry
entity_get_string(hitEnt, EV_SZ_classname, classname, 31)
if (equal(classname, "sentry_base"))
l_sentry = entity_get_edict(hitEnt, BASE_ENT_SENTRY)

else if (equal(classname, "sentry"))
l_sentry = hitEnt
else
break

if (alwaysReturn)
return l_sentry

new sentryLevel = entity_get_int(l_sentry, SENTRY_INT_LEVEL)
new owner = GetSentryPeople(l_sentry, OWNER)

if (cs_get_user_team(owner) == cs_get_user_team(id) && sentryLevel < 2)
{

#if defined DISALLOW_OWN_UPGRADES
// Don't allow builder to upgrade his own sentry first time.
if (sentryLevel == SENTRY_LEVEL_1 && id == owner)
break
#endif
#if defined DISALLOW_TWO_UPGRADES
// Don't allow upgrader to upgrade again.
if (sentryLevel == SENTRY_LEVEL_2 && id == GetSentryPeople(l_sentry, UPGRADER_1))
break
#endif
sentry = l_sentry
}
break
}

return sentry
}

public SentryRadarBlink(parm[2])
{
// 0 = player
// 1 = sentry
if (!is_user_connected(parm[0]) || !is_valid_ent(parm[1]))
return

new Float:sentryOrigin[3]
entity_get_vector(parm[1], EV_VEC_origin, sentryOrigin)

message_begin(MSG_ONE, g_msgHostagePos, {0,0,0}, parm[0])
write_byte(parm[0])
write_byte(SENTRY_RADAR)
write_coord(floatround(sentryOrigin[0]))
write_coord(floatround(sentryOrigin[1]))
write_coord(floatround(sentryOrigin[2]))
message_end()

message_begin(MSG_ONE, g_msgHostageK, {0,0,0}, parm[0])
write_byte(SENTRY_RADAR)
message_end()

new usermenuid, keys
get_user_menu(parm[0], usermenuid, keys)
if (g_menuId == usermenuid)
set_task(1.5, "SentryRadarBlink", TASKID_SENTRYONRADAR + parm[1], parm, 2)
}

stock GetClosestSentry(id)
{
// Find closest sentry
new sentry = 0, closestSentry = 0, Float:closestDistance, Float:distance
while ((sentry = find_ent_by_class(sentry, "sentry")))
{
if (GetSentryPeople(sentry, OWNER) != id)
continue

distance = entity_range(id, sentry)
if (distance < closestDistance || closestSentry == 0)
{
closestSentry = sentry
closestDistance = distance
}
}

return closestSentry
}

public DestroySpyCam(parms[3])
{
new id = parms[0]
new spycam = parms[1]
new sentry = parms[2]
g_inSpyCam[id - 1] = false

// If user is still around, set his view back
if (is_user_connected(id))
engfunc(EngFunc_SetView, id, id)

// Remove connection from sentry (this sentry could've been removed because of a newround, or it was destroyed...)
if (is_valid_ent(sentry) && entity_get_edict(sentry, SENTRY_ENT_SPYCAM) == spycam)
entity_set_edict(sentry, SENTRY_ENT_SPYCAM, 0)

remove_entity(spycam)
}

sentry_upgrade(id, sentry)
{
new sentryLevel = entity_get_int(sentry, SENTRY_INT_LEVEL)
if (entity_get_int(sentry, SENTRY_INT_FIRE) == SENTRY_FIREMODE_NUTS)
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_SENTRY_GUN_DETONATED");

cssbColoredPrint(id, szMessage);

return
}
else if (get_user_team(id) != entity_get_int(sentry, SENTRY_INT_TEAM))
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_ONLY_UPGRADE_YOUR_OWN");

cssbColoredPrint(id, szMessage);

return
}
#if defined DISALLOW_OWN_UPGRADES
else if (sentryLevel == SENTRY_LEVEL_1 && GetSentryPeople(sentry, OWNER) == id)
{
return
}
#endif
#if defined DISALLOW_TWO_UPGRADES
else if (sentryLevel == SENTRY_LEVEL_2 && GetSentryPeople(sentry, UPGRADER_1) == id)
{
return
}

#endif
sentryLevel++
new bool:newLevelIsOK = true, upgraderField
switch (sentryLevel)
{
case SENTRY_LEVEL_2:
{
entity_set_model(sentry, "models/sentries/sentry2.mdl")
upgraderField = UPGRADER_1
}
case SENTRY_LEVEL_3:
{
entity_set_model(sentry, "models/sentries/sentry3.mdl")
upgraderField = UPGRADER_2
}
default:
{
// Error... can only upgrade to level 2 and 3... so far! ;-)
newLevelIsOK = false
}
}

if (newLevelIsOK)
{
if (cs_get_user_money(id) - fCostSentryGuns(sentryLevel) < 0)
{
format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_MONEY_UPGRADE",
fCostSentryGuns(sentryLevel));

cssbColoredPrint(id, szMessage);

return
}

cs_set_user_money(id, cs_get_user_money(id) - fCostSentryGuns(sentryLevel))

new Float:mins[3], Float:maxs[3]
mins[0] = -16.0
mins[1] = -16.0
mins[2] = 0.0
maxs[0] = 16.0
maxs[1] = 16.0
maxs[2] = 48.0 // 4.0
entity_set_size(sentry, mins, maxs)
emit_sound(sentry, CHAN_AUTO, "sentries/turrset.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
entity_set_int(sentry, SENTRY_INT_LEVEL, sentryLevel)
entity_set_float(sentry, EV_FL_health, g_HEALTHS[sentryLevel])
entity_set_float(entity_get_edict(sentry, SENTRY_ENT_BASE), EV_FL_health, g_HEALTHS[0])
SetSentryPeople(sentry, upgraderField, id)

if (id != GetSentryPeople(sentry, OWNER))
{
new upgraderName[32]
get_user_name(id, upgraderName, 31)

format(szMessage, sizeof(szMessage) - 1, "^x01[^x03%L^x01] ^x04%L",
LANG_PLAYER,"WC3SHM_SG_CHATTAG",
LANG_PLAYER,"WC3SHM_SG_UPGRADED_SG_LVL",
upgraderName,
sentryLevel + 1);

cssbColoredPrint(GetSentryPeople(sentry, OWNER), szMessage);

}
}
}

stock userviewhitpoint(index, Float:hitorigin[3])
{
if (!is_user_connected(index))
{
// Error
log_amx("ERROR in plugin - %d is not a valid player index", index)
return 0
}
new Float:origin[3], Float:pos[3], Float:v_angle[3], Float:vec[3], Float:f_dest[3]

entity_get_vector(index, EV_VEC_origin, origin)
entity_get_vector(index, EV_VEC_view_ofs, pos)

pos[0] += origin[0]
pos[1] += origin[1]
pos[2] += origin[2]

entity_get_vector(index, EV_VEC_v_angle, v_angle)

engfunc(EngFunc_AngleVectors, v_angle, vec, 0, 0)

f_dest[0] = pos[0] + vec[0] * 9999
f_dest[1] = pos[1] + vec[1] * 9999
f_dest[2] = pos[2] + vec[2] * 9999

return trace_line(index, pos, f_dest, hitorigin)
}

stock entityviewhitpoint(index, Float:origin[3], Float:hitorigin[3])
{
if (!is_valid_ent(index))
{
// Error
log_amx("ERROR in plugin - %d is not a valid entity index", index)
return 0
}
new Float:angle[3], Float:vec[3], Float:f_dest[3]

entity_get_vector(index, EV_VEC_angles, angle)

engfunc(EngFunc_AngleVectors, angle, vec, 0, 0)

f_dest[0] = origin[0] + vec[0] * 9999
f_dest[1] = origin[1] + vec[1] * 9999
f_dest[2] = origin[2] + vec[2] * 9999

return trace_line(index, origin, f_dest, hitorigin)
}


public ResetArmouryFalse()
{
g_resetArmouryThisRound = false
}
/*
stock spambits(to, bits)
{
new buffer[512], len = 0
for (new i = 31; i >= 0; i--)
{
len += format(buffer[len], 511 - len, "%d", bits & (1<<i) ? 1 : 0)
}
client_print(to, print_chat, buffer)
server_print(buffer)
}*/

public displaysentrystatus(parms[2])
{
// parm 0 = player
// parm 1 = team
if (!GetStatusTrigger(parms[0]))
return

if(parms[1] == 1)
set_hudmessage(255,51,0, -1.0, 0.35, 0, 0.0, STATUSINFOTIME + 0.1, 0.0, 0.0, 2) // STATUSINFOTIME + 0.1 = overlapping a little..

if(parms[1] == 2)
set_hudmessage(0,153,255, -1.0, 0.35, 0, 0.0, STATUSINFOTIME + 0.1, 0.0, 0.0, 2) // STATUSINFOTIME + 0.1 = overlapping a little..

show_hudmessage(parms[0], g_sentryStatusBuffer[parms[0] - 1])

set_task(STATUSINFOTIME, "displaysentrystatus", TASKID_SENTRYSTATUS + parms[0], parms, 2)
}


ResetArmoury()
{
// Find all armoury_entity:s, restore their initial origins
new entity = 0, Float:NULLVELOCITY[3] = {0.0, 0.0, 0.0}, Float:origin[3]
while ((entity = find_ent_by_class(entity, "armoury_entity")))
{
// Reset speed in case it's flying around...
entity_set_vector(entity, EV_VEC_velocity, NULLVELOCITY)

// Get origin and set it.
entity_get_vector(entity, EV_VEC_vuser1, origin)
entity_set_origin(entity, origin)
}
}

public InitArmoury()
{
// Find all armoury_entity:s, store their initial origins
new entity = 0, Float:origin[3], counter = 0
while ((entity = find_ent_by_class(entity, "armoury_entity")))
{
entity_get_vector(entity, EV_VEC_origin, origin)
entity_set_vector(entity, EV_VEC_vuser1, origin)
counter++
}
if (counter > 0)
g_hasArmouries = true
}

stock getnumbers(number, wordnumbers[], length)
{
if (number < 0)
{
format(wordnumbers, length, "error")
return
}

new numberstr[20]
num_to_str(number, numberstr, 19)
new stlen = strlen(numberstr), bool:getzero = false, bool:jumpnext = false
if (stlen == 1)
getzero = true

do
{
if (jumpnext)
jumpnext = false

else if (numberstr[0] != '0')
{
switch (stlen)
{
case 9:
{
if (getsingledigit(numberstr[0], wordnumbers, length))
format(wordnumbers, length, "%s hundred%s", wordnumbers, numberstr[1] == '0' && numberstr[2] == '0' ? " million" : "")
}

case 8:
{
jumpnext = gettens(wordnumbers, length, numberstr)

if (jumpnext)
format(wordnumbers, length, "%s million", wordnumbers)
}

case 7:
{
getsingledigit(numberstr[0], wordnumbers, length)
format(wordnumbers, length, "%s million", wordnumbers)
}

case 6:
{
if (getsingledigit(numberstr[0], wordnumbers, length))
format(wordnumbers, length, "%s hundred%s", wordnumbers, numberstr[1] == '0' && numberstr[2] == '0' ? " thousand" : "")
}

case 5:
{
jumpnext = gettens(wordnumbers, length, numberstr)
if (numberstr[0] == '1' || numberstr[1] == '0')
format(wordnumbers, length, "%s thousand", wordnumbers)
}

case 4:
{
getsingledigit(numberstr[0], wordnumbers, length)
format(wordnumbers, length, "%s thousand", wordnumbers)
}

case 3:
{
getsingledigit(numberstr[0], wordnumbers, length)
format(wordnumbers, length, "%s hundred", wordnumbers)
}

case 2: jumpnext = gettens(wordnumbers, length, numberstr)
case 1:
{
getsingledigit(numberstr[0], wordnumbers, length, getzero)
break // could've trimmed, but of no use here
}

default:
{
format(wordnumbers, length, "%s TOO LONG", wordnumbers)
break
}
}
}

jghg_trim(numberstr, length, 1)
stlen = strlen(numberstr)
}

while (stlen > 0)

// Trim a char from left if first char is a space (very likely)
if (wordnumbers[0] == ' ')
jghg_trim(wordnumbers, length, 1)
}

// Returns true if next char should be jumped
stock bool:gettens(wordnumbers[], length, numberstr[])
{
new digitstr[11], bool:dont = false, bool:jumpnext = false
switch (numberstr[0])
{
case '1':
{
jumpnext = true
switch (numberstr[1])
{
case '0': digitstr = "ten"
case '1': digitstr = "eleven"
case '2': digitstr = "twelve"
case '3': digitstr = "thirteen"
case '4': digitstr = "fourteen"
case '5': digitstr = "fifteen"
case '6': digitstr = "sixteen"
case '7': digitstr = "seventeen"
case '8': digitstr = "eighteen"
case '9': digitstr = "nineteen"
default: digitstr = "TEENSERROR"
}
}

case '2': digitstr = "twenty"
case '3': digitstr = "thirty"
case '4': digitstr = "fourty"
case '5': digitstr = "fifty"
case '6': digitstr = "sixty"
case '7': digitstr = "seventy"
case '8': digitstr = "eighty"
case '9': digitstr = "ninety"
case '0': dont = true // do nothing
default : digitstr = "TENSERROR"
}

if (!dont)
format(wordnumbers, length, "%s %s", wordnumbers, digitstr)

return jumpnext
}

// Returns true when sets, else false
stock getsingledigit(digit[], numbers[], length, bool:getzero = false)
{
new digitstr[11]
switch (digit[0])
{
case '1': digitstr = "one"
case '2': digitstr = "two"
case '3': digitstr = "three"
case '4': digitstr = "four"
case '5': digitstr = "five"
case '6': digitstr = "six"
case '7': digitstr = "seven"
case '8': digitstr = "eight"
case '9': digitstr = "nine"
case '0':
{
if (getzero)
digitstr = "zero"
else
return false
}
default : digitstr = "digiterror"
}
format(numbers, length, "%s %s", numbers, digitstr)

return true
}

stock jghg_trim(stringtotrim[], len, charstotrim, bool:fromleft = true)
{
if (charstotrim <= 0)
return

if (fromleft)
{
new maxlen = strlen(stringtotrim)
if (charstotrim > maxlen)
charstotrim = maxlen

format(stringtotrim, len, "%s", stringtotrim[charstotrim])
}

else
{
new maxlen = strlen(stringtotrim) - charstotrim
if (maxlen < 0)
maxlen = 0

format(stringtotrim, maxlen, "%s", stringtotrim)
}
}

BotBuild(bot, Float:closestTime = 0.1, Float:longestTime = 5.0)
{
// This function should only be used to build sentries at objective related targets.
// So as to not try to build all the time if recently started a build task when touched a objective related target
if (task_exists(bot))
return

new teamSentriesNear = GetStuffInVicinity(bot, BOT_MAXSENTRIESDISTANCE, true, "sentry") + GetStuffInVicinity(bot, BOT_MAXSENTRIESDISTANCE, true, "sentrybase")
if (teamSentriesNear >= BOT_MAXSENTRIESNEAR)
return;

new Float:ltime = random_float(closestTime, longestTime)
set_task(ltime, "sentry_build", bot)
}

public sentry_build_randomlybybot(taskid_and_id)
{
//Check if the player is allowed to build
if(!g_allowBuild)
return

if (!is_user_alive(taskid_and_id - TASKID_BOTBUILDRANDOMLY))
return

// Now finally do a short check if there already are enough (2-3 sentries) in this vicinity... then don't build.
new teamSentriesNear = GetStuffInVicinity(taskid_and_id - TASKID_BOTBUILDRANDOMLY, BOT_MAXSENTRIESDISTANCE, true, "sentry") + GetStuffInVicinity(taskid_and_id - TASKID_BOTBUILDRANDOMLY, BOT_MAXSENTRIESDISTANCE, true, "sentrybase")
if (teamSentriesNear >= BOT_MAXSENTRIESNEAR)
return;

sentry_build(taskid_and_id - TASKID_BOTBUILDRANDOMLY)
}

GetStuffInVicinity(entity, const Float:RADIUS, bool:followTeam, STUFF[])
{
new classname[32], sentryTeam, nrOfStuffNear = 0
entity_get_string(entity, EV_SZ_classname, classname, 31)
if (followTeam)
{
if (equal(classname, "player"))
sentryTeam = get_user_team(entity)
else if (equal(classname, "sentry"))
sentryTeam = entity_get_int(entity, SENTRY_INT_TEAM)
}

if (followTeam)
{
if (equal(STUFF, "sentry"))
{
for (new i = 0; i < g_sentriesNum; i++)
{
if (g_sentries[i] == entity || (followTeam && entity_get_int(g_sentries[i], SENTRY_INT_TEAM) != sentryTeam) || entity_range(g_sentries[i], entity) > RADIUS)
continue

nrOfStuffNear++
}
}
else if (equal(STUFF, "sentrybase"))
{
new ent = 0
while ((ent = find_ent_by_class(ent, STUFF)))
{
// Don't count if:
// If follow team then if team is not same
// If ent is the same as what we're searching from, which is entity
// Don't count a base if it has a head, we consider sentry+base only as one item (a sentry)
// Or if out of range
if ((followTeam && entity_get_int(ent, BASE_INT_TEAM) != sentryTeam)
|| ent == entity
|| entity_get_edict(ent, BASE_ENT_SENTRY) != 0
|| entity_range(ent, entity) > RADIUS)
continue

nrOfStuffNear++
}
}
}
return nrOfStuffNear
}

BotBuildRandomly(bot, Float:closestTime = 0.1, Float:longestTime = 5.0)
{
// This function is used to stark tasks that will build sentries randomly regardless of map objectives and its targets.
new Float:ltime = random_float(closestTime, longestTime)
set_task(ltime, "sentry_build_randomlybybot", TASKID_BOTBUILDRANDOMLY + bot)
}

public botbuildsrandomly(parm[1])
{
if (!is_user_connected(parm[0]))
return

new Float:ltime = random_float(BOT_WAITTIME_MIN, BOT_WAITTIME_MAX)
new Float:ltime2 = ltime + random_float(BOT_NEXT_MIN, BOT_NEXT_MAX)
BotBuildRandomly(parm[0], ltime, ltime2)

set_task(ltime2, "botbuildsrandomly", 0, parm, 1)
}

fCostSentryGuns(i)
{
switch(i)
{
case 0: return get_pcvar_num(iCvarSentryCost1)
case 1: return get_pcvar_num(iCvarSentryCost2)
case 2: return get_pcvar_num(iCvarSentryCost3)
}
return 0;
}


Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   Цитировать сообщение
Статус пользователя Naiteki
сообщение 2.3.2015, 13:00
Сообщение #2


Стаж: 12 лет

Сообщений: 96
Благодарностей: 10
Полезность: < 0

Мне тоже интересно:
https://c-s.net.ua/forum/topic71473.html
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя ThePhoenix
сообщение 2.3.2015, 14:43
Сообщение #3


Стаж: 11 лет

Сообщений: 2723
Благодарностей: 533
Полезность: 40

у меня вроде как миррора пушки,но староваты (3 лвла maх) и их может разбить либо противник,либо ты сам)
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя 192168099
сообщение 2.3.2015, 15:49
Сообщение #4


Стаж: 13 лет

Сообщений: 78
Благодарностей: 26
Полезность: 204

Народ на морозе, уже не первый раз спрашивали этот вопрос, но ни кто не хочет помочь.
По сути дела, там походу надо несколько строчек дописать, но вот только какие ?...
Покупать пушки от Миррора, бесполезность, не вижу смысла, как по мне, так вроде лучше написать скриптеру, что бы он тебе допилил этот нюанс с пушкой...
Задаюсь вопросом, почему изначально при написании этого плагина, автор сам этого не учёл ?
Хочу вот к этой версии плагина допилить анти-урон для пушек...
Скрытый текст
Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя ThePhoenix
сообщение 2.3.2015, 16:21
Сообщение #5


Стаж: 11 лет

Сообщений: 2723
Благодарностей: 533
Полезность: 40

ps.gif Пушки не покупал smile.gif
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя miRror
сообщение 2.3.2015, 16:53
Сообщение #6


Стаж: 15 лет

Сообщений: 1151
Благодарностей: 1002
Полезность: 967

Меценат Меценат

Цитата(192168099 @ 2.3.2015, 15:49) *
Народ на морозе, уже не первый раз спрашивали этот вопрос, но ни кто не хочет помочь.
По сути дела, там походу надо несколько строчек дописать, но вот только какие ?...
Покупать пушки от Миррора, бесполезность, не вижу смысла, как по мне, так вроде лучше написать скриптеру, что бы он тебе допилил этот нюанс с пушкой...
Задаюсь вопросом, почему изначально при написании этого плагина, автор сам этого не учёл ?
Хочу вот к этой версии плагина допилить анти-урон для пушек...
Скрытый текст
Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение

Это почему интересно не имеет смысла?
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Templar
сообщение 2.3.2015, 16:54
Сообщение #7
Иконка группы

Стаж: 18 лет

Сообщений: 2680
Благодарностей: 978
Полезность: 860

Меценат Меценат

miRror, будь человеком, поставь проверку на мой плагин :)
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя miRror
сообщение 2.3.2015, 17:03
Сообщение #8


Стаж: 15 лет

Сообщений: 1151
Благодарностей: 1002
Полезность: 967

Меценат Меценат

В инклюды:

Код:
#include <hamsandwich>


После инклюдов:

Код:
#define is_valid_player(%1) ( 1 <= %1 <= g_iMaxPlayers )


В plugin_init:

Код:
RegisterHam ( Ham_TakeDamage, "func_breakable", "fw_TakeDamage" )


В свободном месте:

Код:
public fw_TakeDamage ( ent, idinflictor, idattacker, Float:damage, damagebits )
{
if ( !pev_valid ( ent ) )
return HAM_IGNORED

new sClassname[11]
pev ( ent, pev_classname, sClassname, charsmax ( sClassname ) )

if ( equal ( sClassname, "sentry" ) || equal ( sClassname, "sentrybase" ) )
{
new iOwner = GetSentryPeople ( ent, OWNER )

if ( !is_user_connected ( iOwner ) || !is_valid_player ( iOwner ) || !is_user_connected ( idattacker ) || !is_valid_player ( idattacker ) )
return HAM_IGNORED

if ( cs_get_user_team ( iOwner ) == cs_get_user_team ( idattacker ) && idattacker != iOwner )
return HAM_SUPERCEDE

if ( idattacker == iOwner )
return HAM_IGNORED
}
return HAM_IGNORED
}
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 3 раз
   + Цитировать сообщение
Статус пользователя Templar
сообщение 2.3.2015, 18:04
Сообщение #9
Иконка группы

Стаж: 18 лет

Сообщений: 2680
Благодарностей: 978
Полезность: 860

Меценат Меценат

Чтот у меня не получается вставить.. Что не так делаю?


Прикрепленные файлы:
Прикрепленное изображение

Прикрепленные файлы:
Прикрепленный файл  wc3_sentry_guns.sma ( 77,54 килобайт ) Кол-во скачиваний: 25
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
marik
сообщение 2.3.2015, 18:14
Сообщение #10
Стаж: 12 лет

Сообщений: 593
Благодарностей: 130
Полезность: < 0

192168099,
Конечно нет смысла покупать ! он баг так и не убрал ! периодически падает сервер
Это факт ! а он все продолжает пихать их всем попало
У него у самого такие проблемы с сервером ! ап тайм я уверен и до 2-3к не доходит

Отредактировал: marik, - 2.3.2015, 18:15
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
amxservak
сообщение 2.3.2015, 18:17
Сообщение #11
Стаж: 15 лет

Сообщений: 163
Благодарностей: 81
Полезность: < 0

Поддерживаю покупать пушки это на столько глупо, такие плагины должны быть в свободном доступе. Что и есть, все сливают рано или поздно :)
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
marik
сообщение 2.3.2015, 18:21
Сообщение #12
Стаж: 12 лет

Сообщений: 593
Благодарностей: 130
Полезность: < 0

amxservak,
Пушки у него отличные ! просто он сам не знает где прокол ! за такие пушки не грех и денег дать ! но пока падает у него и у всех купивший да что говорить каждый школьник знает что от его пушек сервер падает ! даже его новые с 4 уровнем (стреляют ракетами ) с этими тоже проблема
Сообщение удалят и могут процент влепить а что ? это все факты
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
amxservak
сообщение 2.3.2015, 18:25
Сообщение #13
Стаж: 15 лет

Сообщений: 163
Благодарностей: 81
Полезность: < 0

Цитата(marik @ 2.3.2015, 19:21) *
amxservak,
Пушки у него отличные ! просто он сам не знает где прокол ! за такие пушки не грех и денег дать ! но пока падает у него и у всех купивший да что говорить каждый школьник знает что от его пушек сервер падает ! даже его новые с 4 уровнем (стреляют ракетами ) с этими тоже проблема
Сообщение удалят и могут процент влепить а что ? это все факты

dntknw.gif У богатых свои причуды...Но лично я не заплатил бы за эти пушки.За очень интересный плагин, мод заплатил...

Я думал у меня сервер падает из-за того что паблик пушки, а нет падает у всех я так понял.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
marik
сообщение 2.3.2015, 18:32
Сообщение #14
Стаж: 12 лет

Сообщений: 593
Благодарностей: 130
Полезность: < 0

amxservak,
Я полностью мод брал (так для инфы)
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Bloo
сообщение 2.3.2015, 18:34
Сообщение #15


Стаж: 12 лет

Сообщений: 15547
Благодарностей: 6971
Полезность: 1206

Цитата
Сообщение удалят и могут процент влепить а что ? это все факты

С какой стати его удалят и выдадут %? У вас кажется паранойя...
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
marik
сообщение 2.3.2015, 18:41
Сообщение #16
Стаж: 12 лет

Сообщений: 593
Благодарностей: 130
Полезность: < 0

Bloo,
Тогда была тема на счет мирора ! мы в двоем описывали проблемы не грубили и тут почистили все и ему процент влепили ! одним словом проехали !
Пушки хороший и мод тоже (но если бы не эти рестарты ) а так все устраивает
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя miRror
сообщение 2.3.2015, 18:45
Сообщение #17


Стаж: 15 лет

Сообщений: 1151
Благодарностей: 1002
Полезность: 967

Меценат Меценат

Пушки у меня го*в*но впрочем как и ты) На неделе появятся новые пушки, переписанные с нуля, тогда я запляшем.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
amxservak
сообщение 2.3.2015, 18:50
Сообщение #18
Стаж: 15 лет

Сообщений: 163
Благодарностей: 81
Полезность: < 0

Цитата(miRror @ 2.3.2015, 19:45) *
Пушки у меня го*в*но впрочем как и ты) На неделе появятся новые пушки, переписанные с нуля, тогда я запляшем.

cbf1b2bfde1a.gif переходить на личность это очень умно.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя miRror
сообщение 2.3.2015, 18:54
Сообщение #19


Стаж: 15 лет

Сообщений: 1151
Благодарностей: 1002
Полезность: 967

Меценат Меценат

Цитата(amxservak @ 2.3.2015, 18:50) *
cbf1b2bfde1a.gif переходить на личность это очень умно.

Нормально, особенно если знать, что это за человек.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя miRror
сообщение 2.3.2015, 19:16
Сообщение #20


Стаж: 15 лет

Сообщений: 1151
Благодарностей: 1002
Полезность: 967

Меценат Меценат

Цитата(Templar @ 2.3.2015, 18:04) *
Чтот у меня не получается вставить.. Что не так делаю?


Еще создай перед plugin_init:

Код:
new g_iMaxPlayers


И в plugin_init:

Код:
g_iMaxPlayers = get_global_int(GL_maxClients)
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 2 раз
   + Цитировать сообщение
3 страниц V   1 2 »
 
Ответить в данную темуНачать новую тему
 
0 пользователей и 1 гостей читают эту тему: