/*
HLPresents v. 0.1
by serfreeman1337
http://gf.hldm.org/ AGHL.RU DevTeam [
http://aghl.ru/forum ]
Thanks to:
- Safety1st
- Lev
*/
#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta_util>
#include <hamsandwich>
enum _:cvars {
CVAR_POINT,
CVAR_SPAWN_MODE,
CVAR_SPAWN,
CVAR_COUNT,
CVAR_RENDER,
CVAR_FLOATING,
CVAR_DLIGHT
}
enum _:presents {
PP_MODEL[128],
PP_SOUND_SPAWN[128],
PP_SOUND_PICKUP[128],
Array:PP_GIFTS, // :p
Float:PP_CHANCE
}
enum _:gifts {
GF_PLUGIN_ID,
GF_FUNCTION_ID,
GF_TYPE,
Float:GF_CHANCE
}
new cvar[cvars]
new Array:g_Presents
new Array:g_Gifts
new Array:g_SpawnPoints
new Array:g_GiveItems
new Trie:g_SpawnsTemp
new g_InitPosCount,g_InitPresentsCount,g_InitGiftsCount
new pointSpawn
new Float:respawnTime,g_SpawnMode,lastRespawn,nextRespawn
new g_PresRender[3],g_PresRenderType,g_PresFloat,g_PresDlight
new const present_classname[] = "info_present"
new const Float:ent_MINS[3] = { -2.0, -2.0, -4.0 }
new const Float:ent_MAXS[3] = { 2.0, 2.0, 4.0 }
new const HLPresents_Dir[] = "/HLPresents/"
new bool:g_MLoaded
// credits to Turranga_Leela
new const Float:direction[][] =
{
{0.0, 0.0, 20.0},
{0.0, 0.0, -20.0}
}
enum _:Velocity_Mode
{
Velocity_Up = 1,
Velocity_Down
}
#define Present_Indefer pev_iuser4
#define Present_Position pev_iuser3
#define Velocity_Vector pev_iuser2
#define Ent_Filter pev_iuser1
#define Present_Spawn_Time pev_fuser4
#define Present_Block pev_fuser3
#define None 0
new shock,g_screenfade
#define SPTASKID 61337
#define PLUGIN "HLPresents"
#define VERSION "0.1"
#define AUTHOR "serfreeman1337"
public plugin_precache(){
register_plugin(PLUGIN,VERSION,AUTHOR)
precache_model("models/w_chainammo.mdl")
precache_model("models/w_medkit.mdl")
precache_sound("items/smallmedkit1.wav")
/* Where to spawn presents?
0 - no where
1 - use predefined points in map file
2 - at player death point
4 - at items / weapons points
*/
cvar[CVAR_POINT] = register_cvar("hlp_point","2")
/* When to spawn presents? */
cvar[CVAR_SPAWN] = register_cvar("hlp_spawn_time","120.0")
/* Presents spawn mode
0 - dont spawn
1 - spawn all by timer
2 - spawn all by server overall time
3 - spawn in half-life style
*/
cvar[CVAR_SPAWN_MODE] = register_cvar("hlp_spawn_mode","3")
/* How many presents will be? */
cvar[CVAR_COUNT] = register_cvar("hlp_count","3")
/* How render presents?
-1 - dont render
random - random render
<r> <g> <b> - sets render
*/
cvar[CVAR_RENDER] = register_cvar("hlp_render","random")
/* Toogle presents floating? */
cvar[CVAR_FLOATING] = register_cvar("hlp_floating","1")
/* Use dlight for presents? */
cvar[CVAR_DLIGHT] = register_cvar("hlp_dlight","1")
new fpath[256]
get_configsdir(fpath,255)
formatex(fpath,255,"%s%ssettings.ini",fpath,HLPresents_Dir)
new f = fopen(fpath,"r")
g_Presents = ArrayCreate(presents)
g_Gifts = ArrayCreate(gifts)
g_SpawnPoints = ArrayCreate(3)
g_GiveItems = ArrayCreate(32)
g_SpawnsTemp = TrieCreate()
shock = precache_model("sprites/shockwave.spr")
if(!f){
log_amx("failed to load configuration file")
return
}
new buffer[512],parseState,tempData[presents],tempGifts[gifts], bool:ppSet
/* cfg file parse state:
0 - init
1 - parse cvars
2 - parse presents
3 - parse gifts
*/
while(!feof(f)){
fgets(f,buffer,511)
trim(buffer)
if(!strlen(buffer))
continue
if(buffer[0] == ';')
continue
if(!strcmp(buffer,"[cvars]")){
parseState = 1
continue
}else if(!strcmp(buffer,"[presents]")){
parseState = 2
continue
}else if(!strcmp(buffer,"[gifts]")){
parseState = 3
continue
}
switch(parseState){
case 1:{
new cvar[32],val[16]
strbreak(buffer,cvar,31,val,15)
trim(cvar)
trim(val)
if(val[0] == 0 || isalpha(val[0]) || val[0] == '"'){
set_cvar_string(cvar,val)
}
else if(contain(val,"."))
set_cvar_float(cvar,floatstr(val))
else{
set_cvar_num(cvar,str_to_num(val))
}
}
case 2:{
if(!strcmp(buffer,"<>")){
if(ppSet){
ArrayPushArray(g_Presents,tempData)
precache_model(tempData[PP_MODEL])
if(strlen(tempData[PP_SOUND_SPAWN]))
precache_sound(tempData[PP_SOUND_SPAWN])
if(strlen(tempData[PP_SOUND_PICKUP]))
precache_sound(tempData[PP_SOUND_PICKUP])
arrayset(tempData,0,presents)
ppSet = false
}
continue
}
new set[16],val[128]
strtok(buffer,set,15,val,127,'=',1)
replace(val,127,"=","")
trim(set)
trim(val)
if(!strcmp(set,"model")){
copy(tempData[PP_MODEL],127,val)
continue
}
if(!strcmp(set,"sound_spawn")){
copy(tempData[PP_SOUND_SPAWN],127,val)
continue
}
if(!strcmp(set,"sound_pickup")){
copy(tempData[PP_SOUND_PICKUP],127,val)
continue
}
if(!strcmp(set,"chance")){
tempData[PP_CHANCE] = _:floatstr(val)
continue
}
if(!strcmp(set,"gifts")){
new stPos,ePos,eTemp,rawGift[4],len
tempData[PP_GIFTS] = _:ArrayCreate(4)
if(!strcmp(val,"all")){
ArrayPushCell(tempData[PP_GIFTS],-1) // по идеии должно быть -2, сейчас проверим
ppSet = true
continue
}
// parse whole entry levels
do{
eTemp = strfind(val,",",0,stPos)
if(eTemp > -1)
ePos = eTemp
else
ePos = strlen(val)
len = ePos - stPos
formatex(rawGift,len,val[stPos])
stPos = ePos + 1
ArrayPushCell(tempData[PP_GIFTS],str_to_num(val))
}while(strfind(val,",",0,stPos) != -1 || stPos < strlen(val))
ppSet = true
}
}
case 3:{
if(!strcmp(buffer,"<>")){
if(ppSet){
ArrayPushArray(g_Gifts,tempGifts)
arrayset(tempGifts,0,gifts)
ppSet = false
}
continue
}
new set[16],val[368]
strtok(buffer,set,15,val,127,'=',1)
replace(val,367,"=","")
trim(set)
trim(val)
if(!strcmp(set,"chance")){
tempGifts[GF_CHANCE] = _:floatstr(val)
continue
}
if(!strcmp(set,"give")){
new stPos,ePos,eTemp,rawItem[32],len
tempGifts[GF_PLUGIN_ID] = ArraySize(g_GiveItems)
// parse whole entry levels
do{
eTemp = strfind(val,",",0,stPos)
if(eTemp > -1)
ePos = eTemp
else
ePos = strlen(val)
len = ePos - stPos
formatex(rawItem,len,val[stPos])
stPos = ePos + 1
trim(rawItem)
ArrayPushString(g_GiveItems,rawItem)
}while(strfind(val,",",0,stPos) != -1 || stPos < strlen(val))
tempGifts[GF_FUNCTION_ID] = ArraySize(g_GiveItems)
ppSet = true
tempGifts[GF_TYPE] = 2
continue
}
if(!strcmp(set,"plugin")){
tempGifts[GF_PLUGIN_ID] = find_plugin_byfile(val,1)
if(tempGifts[GF_PLUGIN_ID] < 0)
log_amx("unknown plugin ^"%s^"",val)
continue
}
if(!strcmp(set,"function")){
tempGifts[GF_FUNCTION_ID] = get_func_id(val,tempGifts[GF_PLUGIN_ID])
if(tempGifts[GF_FUNCTION_ID] < 0)
log_amx("unknown function ^"%s^" in PluginID: %d",
val,tempGifts[GF_PLUGIN_ID])
ppSet = true
tempGifts[GF_TYPE] = 1
continue
}
}
}
}
fclose(f)
f = 0
pointSpawn = get_pcvar_num(cvar[CVAR_POINT])
if(pointSpawn & 1){
new map[32]
get_mapname(map,31)
get_configsdir(fpath,255)
formatex(fpath,255,"%s%smaps/%s.ini",fpath,HLPresents_Dir,map)
new f = fopen(fpath,"r")
if(f){
new Float:origin[3]
while(!feof(f)){
fgets(f,buffer,511)
trim(buffer)
if(!strlen(buffer) || buffer[0] == ';')
continue
ParseVec(buffer,511,origin)
ArrayPushArray(g_SpawnPoints,origin)
}
fclose(f)
}
}
new temp[32]
get_pcvar_string(cvar[CVAR_RENDER],temp,31)
remove_quotes(temp)
if(!strcmp(temp,"random")){
g_PresRenderType = 2
}else if(str_to_num(temp) == -1){
g_PresRenderType = 0
}else{
new sRgb[3][4]
parse(temp,sRgb[0],3,sRgb[1],3,sRgb[2],3)
g_PresRender[0] = str_to_num(sRgb[0])
g_PresRender[1] = str_to_num(sRgb[1])
g_PresRender[2] = str_to_num(sRgb[2])
g_PresRenderType = 1
}
g_PresFloat = get_pcvar_num(cvar[CVAR_FLOATING])
g_PresDlight = get_pcvar_num(cvar[CVAR_DLIGHT])
g_SpawnMode = get_pcvar_num(cvar[CVAR_SPAWN_MODE])
g_InitPresentsCount = ArraySize(g_Presents)
g_InitPosCount = ArraySize(g_SpawnPoints)
g_InitGiftsCount = ArraySize(g_Gifts)
}
public plugin_init(){
if(pointSpawn & 2) // hook player death for death points
RegisterHam(Ham_Killed,"player","On_Player_Killed_Post",1)
g_screenfade = get_user_msgid("ScreenFade")
register_think(present_classname,"Present_Think")
register_touch(present_classname,"player","Present_Touch")
respawnTime = get_pcvar_float(cvar[CVAR_SPAWN])
// set repeatly presents respawn for current map
switch(g_SpawnMode){
case 1: set_task(respawnTime,"Spawn_Presents",SPTASKID,.flags="b")
case 2: {
lastRespawn = read_last_respawn_time()
nextRespawn = lastRespawn + floatround(respawnTime)
new diff = nextRespawn - get_systime()
set_task(diff > 0 ? float(diff) : 5.0,"Spawn_Presents",SPTASKID)
}
case 3:{
for(new i;i<get_pcvar_num(cvar[CVAR_COUNT]);++i)
set_task(random_float(respawnTime / 2,respawnTime),"Retr_Present",SPTASKID)
}
}
register_clcmd("hlp_spawn_menu","Open_Spawn_Menu",ADMIN_RCON," - opens spawn points editor for HLPresents")
}
public Open_Spawn_Menu(id,level,cid){
if(!cmd_access(id,level,cid,1))
return PLUGIN_HANDLED
if(!g_InitPresentsCount){
client_print(id,print_console,"[HLP] No valid presents for edit.")
return PLUGIN_HANDLED
}
if(!g_MLoaded){
new Float:spOrigin[3]
for(new i;i<ArraySize(g_SpawnPoints);++i){
ArrayGetArray(g_SpawnPoints,i,spOrigin)
new ent = Spawn_One_Present(spOrigin,random_num(0,g_InitPresentsCount - 1))
set_pev(ent,pev_nextthink,get_gametime())
set_pev(ent,Present_Block,1.0)
set_pev(ent,pev_solid,SOLID_NOT)
fm_set_rendering(ent,kRenderFxGlowShell,255,255,0,kRenderNormal,128)
set_pev(ent,Present_Position,i)
set_pev(ent,pev_movetype,MOVETYPE_TOSS)
set_pev(ent,pev_velocity,{0.0,0.0,15.0})
}
client_print(id,print_chat,"[HLP] Total %d spawn points loaded.",ArraySize(g_SpawnPoints))
g_MLoaded = true
remove_task(SPTASKID)
}
new m = menu_create("HLPresents Spawn Menu","Menu_Handler")
menu_additem(m,"Add spawn position","1")
menu_additem(m,"Remove spawn position^n","2")
menu_additem(m,"Save spawn positions","3")
menu_display(id,m)
return PLUGIN_HANDLED
}
public Menu_Handler(id,menu,item){
if(item == MENU_EXIT)
return PLUGIN_HANDLED
new data[6],name[64]
new access,callback
menu_item_getinfo(menu,item,access,data,5,name,63,callback)
new key = str_to_num(data)
new Float:spOrigin[3]
switch(key){
case 1:{
fm_get_aim_origin(id,spOrigin)
new ent = Spawn_One_Present(spOrigin,random_num(0,g_InitPresentsCount - 1))
set_pev(ent,pev_nextthink,0.0)
set_pev(ent,pev_solid,SOLID_NOT)
set_pev(ent,pev_renderfx,kRenderFxDistort)
set_pev(ent,pev_rendermode,kRenderTransAdd)
set_pev(ent,pev_renderamt,128.0)
client_print(id,print_chat,"[HLP] Spawn position added --> [ %.2f %.2f %.2f ]",
spOrigin[0],spOrigin[1],spOrigin[2])
ArrayPushArray(g_SpawnPoints,spOrigin)
}
case 2:{
fm_get_aim_origin(id,spOrigin)
new pp = get_aiment(id)
if(pev_valid(pp)){
new tt = pev(pp,Present_Position)
if(tt > -1){
ArrayGetArray(g_SpawnPoints,tt,spOrigin)
if(spOrigin[0] == 0.0 && spOrigin[1] == 0.0 && spOrigin[2] == 0.0){
client_print(id,print_chat,"[HLP] Unable to locate present for delete.")
menu_display(id,menu)
return PLUGIN_HANDLED
}
client_print(id,print_chat,"[HLP] Spawn position [ %.2f %.2f %.2f ] marked for delete.",
spOrigin[0],spOrigin[1],spOrigin[2])
spOrigin[0] = 0.0
spOrigin[1] = 0.0
spOrigin[2] = 0.0
ArraySetArray(g_SpawnPoints,tt,spOrigin)
fm_set_rendering(pp,kRenderFxGlowShell,255,0,0,kRenderNormal,128)
}else{
client_print(id,print_chat,"[HLP] Unknown present.")
}
}else{
client_print(id,print_chat,"[HLP] Unable to locate present for delete.")
}
}
case 3:{
new fpath[256],map[32]
get_configsdir(fpath,255)
get_mapname(map,31)
formatex(fpath,255,"%s%smaps/%s.ini",fpath,HLPresents_Dir,map)
new Array:savePos = ArrayCreate(3),Float:spOrigin[3],del,ad
for(new i ; i < ArraySize(g_SpawnPoints); ++i){
ArrayGetArray(g_SpawnPoints,i,spOrigin)
if(spOrigin[0] == 0.0 && spOrigin[1] == 0.0 && spOrigin[2] == 0.0){
del ++
continue
}
ArrayPushArray(savePos,spOrigin)
ad++
}
client_print(id,print_chat,"[HLP] Saving to ^"%s^"...",fpath)
new f = fopen(fpath,"w+")
fprintf(f,";^n; %s v. %s^n; by %s
http://gf.hldm.org/^n;^n",
PLUGIN,VERSION,AUTHOR)
fprintf(f,"^n; %s map configuration file^n; %d total^n",
map,ad)
for(new i ; i < ArraySize(savePos) ; ++i){
ArrayGetArray(savePos,i,spOrigin)
fprintf(f,"^n%.2f %.2f %.2f",spOrigin[0],spOrigin[1],spOrigin[2])
}
fprintf(f,"^n^n; %s, Copyright (c) 2013 AGHL.RU Dev Team^n;
http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community",
PLUGIN)
fclose(f)
client_print(id,print_chat,"[HLP] Total %d entries writed and %d deleted.",ad,del)
}
}
menu_display(id,menu)
return PLUGIN_HANDLED
}
public pfn_spawn(ent){
if(pointSpawn & 4){
new classname[32],Float:origin[3]
pev(ent,pev_classname,classname,31)
if(contain(classname,"weapon_") == 0 || contain(classname,"ammo_") == 0|| contain(classname,"item_") == 0){
pev(ent,pev_origin,origin)
ArrayPushArray(g_SpawnPoints,origin)
g_InitPosCount ++
}
}
}
public On_Player_Killed_Post(victim,idattacker){
new Float:origin[3]
pev(victim,pev_origin,origin)
ArrayPushArray(g_SpawnPoints,origin) // add new position at death point
}
public Retr_Present(){
new spCount = ArraySize(g_SpawnPoints)
new Float:origin[3],iL,ppType,tempData[presents],maxCnt,Float:rnd,ent
ppType = -1
iL = CanSpawn(spCount)
if(iL < 0)
return
ArrayGetArray(g_SpawnPoints,iL,origin)
while(ppType == -1){
ppType = random_num(0,g_InitPresentsCount - 1)
ArrayGetArray(g_Presents,ppType,tempData)
rnd = random_float(0.0,100.0)
if(tempData[PP_CHANCE] < rnd)
ppType = -1
if(maxCnt > 10)
break
maxCnt ++
}
if(ppType > -1)
ent = Spawn_One_Present(origin,ppType)
if(ent < 0)
return
set_pev(ent,Present_Position,iL)
set_pev(ent,Present_Spawn_Time,get_gametime())
}
public Spawn_Presents(){
if(!g_InitPresentsCount)
return
// remove old presents
new ent
while((ent = fm_find_ent_by_class(ent,present_classname)))
fm_remove_entity(ent)
new spCount = ArraySize(g_SpawnPoints)
// spawn new presents
new Float:origin[3],iL,ppType,tempData[presents],maxCnt
for(new i ; i < get_pcvar_num(cvar[CVAR_COUNT]) ; ++i){
ppType = -1
iL = CanSpawn(spCount) // check spawn origin
if(iL < 0) // no valid spawn origin
continue
ArrayGetArray(g_SpawnPoints,iL,origin)
new Float:rnd = random_float(0.0,100.0)
while(ppType == -1){
ppType = random_num(0,g_InitPresentsCount - 1)
ArrayGetArray(g_Presents,ppType,tempData)
if(tempData[PP_CHANCE] < rnd)
ppType = -1
if(maxCnt > 10)
break
maxCnt ++
}
if(ppType > -1)
Spawn_One_Present(origin,ppType)
ppType = -1
maxCnt = 0
}
// remove death points
new azaza
while((azaza = ArraySize(g_SpawnPoints)) > g_InitPosCount){
ArrayDeleteItem(g_SpawnPoints,azaza - 1)
}
TrieClear(g_SpawnsTemp)
if(g_SpawnMode == 2){
lastRespawn = get_systime()
nextRespawn = lastRespawn + floatround(respawnTime)
new Float:curRespTime = float(nextRespawn - lastRespawn)
if(curRespTime){
set_task(curRespTime,"Spawn_Presents",SPTASKID)
save_last_respawn_time(get_systime())
}
}
}
public Spawn_One_Present(Float:origin[3],ppType){
if(ppType < 0)
return 0
new ent = fm_create_entity("info_target")
set_pev(ent,pev_classname,present_classname)
new presentData[presents]
ArrayGetArray(g_Presents,ppType,presentData)
engfunc(EngFunc_SetModel,ent,presentData[PP_MODEL])
dllfunc(DLLFunc_Spawn,ent)
engfunc(EngFunc_SetOrigin,ent,origin)
engfunc(EngFunc_DropToFloor,ent)
set_pev(ent,pev_movetype,MOVETYPE_NOCLIP)
engfunc(EngFunc_SetSize,ent,ent_MINS,ent_MAXS)
set_pev(ent,pev_mins,ent_MINS)
set_pev(ent,pev_maxs,ent_MAXS)
set_pev(ent,pev_absmin,ent_MINS)
set_pev(ent,pev_absmax,ent_MAXS)
set_pev(ent,pev_solid,SOLID_TRIGGER)
set_pev(ent,pev_movetype,MOVETYPE_FLYMISSILE)
set_pev(ent,Present_Indefer,ppType)
set_pev(ent,Present_Position,-1)
if(strlen(presentData[PP_SOUND_SPAWN]))
emit_sound(ent,CHAN_ITEM,presentData[PP_SOUND_SPAWN],0.5,ATTN_NORM,0,PITCH_NORM)
switch(g_PresRenderType){
case 1:{
fm_set_rendering(ent,kRenderFxGlowShell,g_PresRender[0],g_PresRender[1],g_PresRender[2],kRenderNormal,255)
}
case 2:{
fm_set_rendering(ent,kRenderFxGlowShell,random_num(100,255),random_num(100,255),random_num(100,255),kRenderNormal,255)
}
}
if(g_PresDlight || g_PresFloat || g_SpawnMode == 3)
set_pev(ent,pev_nextthink,random_float(0.0,0.5)+get_gametime())
return ent
}
public Present_Think(ent){
static mode,Float:angles[3]
if(pev_valid(ent))
{
if(pev(ent,Present_Block))
return
switch(pev(ent, Velocity_Vector))
{
case None, Velocity_Up:
{
mode = Velocity_Up
}
case Velocity_Down:
{
mode = Velocity_Down
}
default:
{
return
}
}
/*pev(ent,pev_angles,angles)
if(angles[1]>=360.0)
angles[1]=0.0
angles[1]+=5.0
set_pev(ent,pev_angles,angles) */
if(g_PresFloat){
set_pev(ent, Velocity_Vector, mode ^ Velocity_Mode)
set_pev(ent, pev_velocity, direction[mode - 1])
set_pev(ent,pev_avelocity,Float:{0.0,50.0,0.0})
}
set_pev(ent,pev_nextthink,1.0+get_gametime())
pev(ent,pev_origin,angles)
new rnd[3]
switch(g_PresRenderType){
case 1:{
rnd[0] = g_PresRender[0]
rnd[1] = g_PresRender[1]
rnd[2] = g_PresRender[2]
}
case 2:{
rnd[0] = random(255)
rnd[1] = random(255)
rnd[2] = random(255)
}
}
shockwave(angles,150,rnd[0],rnd[1],rnd[2])
if(g_PresRenderType)
fm_set_rendering(ent,kRenderFxGlowShell,rnd[0],rnd[1],rnd[2],kRenderNormal,128)
if(g_PresDlight){
engfunc(EngFunc_MessageBegin,MSG_PVS,SVC_TEMPENTITY,angles,0)
write_byte(TE_DLIGHT)
engfunc(EngFunc_WriteCoord,angles[0])
engfunc(EngFunc_WriteCoord,angles[1])
engfunc(EngFunc_WriteCoord,angles[2])
write_byte(15)
write_byte(rnd[0])
write_byte(rnd[1])
write_byte(rnd[2])
write_byte(255)
write_byte(15)
write_byte(1)
message_end()
}
if(g_SpawnMode == 3){
new Float:prTime
pev(ent,Present_Spawn_Time,prTime)
if(prTime + respawnTime < get_gametime()){
new key[16]
new iL = pev(ent,Present_Position)
num_to_str(iL,key,15)
TrieDeleteKey(g_SpawnsTemp,key) // remove marked spawn point
fm_remove_entity(ent)
set_task(random_float(respawnTime / 2,respawnTime),"Retr_Present",SPTASKID)
// remove death points
new azaza
while((azaza = ArraySize(g_SpawnPoints)) > g_InitPosCount){
ArrayDeleteItem(g_SpawnPoints,azaza - 1)
}
}
}
}
}
public Present_Touch(ent,id){
if(!is_user_alive(id))
return PLUGIN_HANDLED
new Float:presentorg[3],ppType
ppType = pev(ent,Present_Indefer)
if(g_SpawnMode == 3){
new key[16]
new iL = pev(ent,Present_Position)
num_to_str(iL,key,15)
TrieDeleteKey(g_SpawnsTemp,key) // remove marked spawn point
set_task(random_float(respawnTime / 2,respawnTime),"Retr_Present",SPTASKID)
}
new presentData[presents],giftData[gifts]
ArrayGetArray(g_Presents,ppType,presentData)
pev(ent,pev_origin,presentorg)
new clor[3]
clor[0] = random_num(0,255)
clor[1] = random_num(0,255)
clor[2] = random_num(0,255)
shockwave(presentorg,500,clor[0],clor[1],clor[2])
UTIL_ScreenFade(id,clor,0.1,0.1,128)
if(strlen(presentData[PP_SOUND_PICKUP]))
client_cmd(id,"spk %s",presentData[PP_SOUND_PICKUP])
//emit_sound(id,CHAN_WEAPON,presentData[PP_SOUND_PICKUP],1.0,ATTN_NONE,0,PITCH_NORM)
fm_remove_entity(ent)
// call give present function
if(!g_InitGiftsCount)
return PLUGIN_CONTINUE
new gfFirst = ArrayGetCell(presentData[PP_GIFTS],0)
gfFirst -- // ну вы поняли
new gfTt
new Float:rnd
new maxcnt
do {
rnd = random_float(0.0,100.0)
switch(gfFirst){
case -2: gfTt = random_num(0,g_InitGiftsCount - 1) // search random gift
case -1: {} // no gifts here
default:{
gfTt = random_num(0,ArraySize(presentData[PP_GIFTS]) - 1) // search random predefined gift
if(gfTt > g_InitGiftsCount)
gfTt = g_InitGiftsCount - 1
gfTt = ArrayGetCell(presentData[PP_GIFTS],gfTt) - 1
}
}
ArrayGetArray(g_Gifts,gfTt,giftData)
maxcnt ++
} while (giftData[GF_CHANCE] < rnd && maxcnt <= 10)
if(giftData[GF_TYPE] == 1){
if(giftData[GF_PLUGIN_ID] != INVALID_PLUGIN_ID && giftData[GF_FUNCTION_ID] != -1){
callfunc_begin_i(giftData[GF_FUNCTION_ID],giftData[GF_PLUGIN_ID])
callfunc_push_int(id)
callfunc_end()
}
}else if(giftData[GF_TYPE] == 2){
new item[32]
for(new i = giftData[GF_PLUGIN_ID]; i < giftData[GF_FUNCTION_ID]; ++i){
ArrayGetString(g_GiveItems,i,item,31)
fm_give_item(id,item)
}
}
return PLUGIN_CONTINUE
}
shockwave(Float:origin[3], radius, r, g, b) { // shockwave effect
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_BEAMCYLINDER )
engfunc(EngFunc_WriteCoord,origin[0])
engfunc(EngFunc_WriteCoord,origin[1])
engfunc(EngFunc_WriteCoord,origin[2])
engfunc(EngFunc_WriteCoord,origin[0])
engfunc(EngFunc_WriteCoord,origin[1])
engfunc(EngFunc_WriteCoord,origin[2]+radius)
write_short(shock)
write_byte(0) // startframe
write_byte(0) // framerate in 0.1's
write_byte(2) // life
write_byte(64) // width
write_byte(255) // noise
write_byte(r)
write_byte(g)
write_byte(b)
write_byte(255) //bright
write_byte(0) //scrollspeed
message_end()
}
UTIL_ScreenFade(id=0,iColor[3]={0,0,0},Float:flFxTime=-1.0,Float:flHoldTime=0.0,iAlpha=0,iFlags=0x0000,bool:bReliable=false,bool:bExternal=false){
if(id&&!is_user_connected(id))
return
new iFadeTime
if(flFxTime==-1.0)
iFadeTime = 4
else
iFadeTime = FixedUnsigned16(flFxTime,1<<12)
new MSG_DEST
if(bReliable)
MSG_DEST = id ? MSG_ONE : MSG_ALL
else
MSG_DEST = id ? MSG_ONE_UNRELIABLE : MSG_BROADCAST
if(bExternal){
emessage_begin(MSG_DEST,g_screenfade, _,id)
ewrite_short(iFadeTime)
ewrite_short(FixedUnsigned16(flHoldTime,1<<12 ))
ewrite_short(iFlags)
ewrite_byte(iColor[0])
ewrite_byte(iColor[1])
ewrite_byte(iColor[2])
ewrite_byte(iAlpha)
emessage_end()
}
else{
message_begin(MSG_DEST,g_screenfade,_, id)
write_short(iFadeTime)
write_short(FixedUnsigned16(flHoldTime,1<<12 ))
write_short(iFlags)
write_byte(iColor[0])
write_byte(iColor[1])
write_byte(iColor[2])
write_byte(iAlpha)
message_end()
}
}
FixedUnsigned16(Float:flValue, iScale){
new iOutput;
iOutput = floatround(flValue * iScale);
if ( iOutput < 0 )
iOutput = 0;
if ( iOutput > 0xFFFF )
iOutput = 0xFFFF;
return iOutput;
}
// from KORD_12.7 displacer plugin
CanSpawn(maxPoints)
{
new ent, alert, i,key[6];
do
{
for (i = random_num(1, 10); i > 0; i-- )
ent = random_num(0,maxPoints - 1)
if (alert ++ > 10) return -1;
}
while (!IsSpawnPointValid(ent,maxPoints));
num_to_str(ent,key,5)
TrieSetCell(g_SpawnsTemp,key,1) // mark spawn position
return ent;
}
bool:IsSpawnPointValid(ent,maxPoints){
if(ent >= maxPoints)
return false
new key[6]
num_to_str(ent,key,5)
// already spawned present here
if(TrieKeyExists(g_SpawnsTemp,key))
return false
return true
}
// Parse Vector Function by KORD_12.7
ParseVec(szString[], iStringLen, Float: Vector[3]){
new i;
new szTemp[32];
arrayset(_:Vector, 0, 3);
while (szString[0] != 0 && strtok(szString, szTemp, charsmax(szTemp), szString, iStringLen, ' ', 1))
{
Vector[i++] = str_to_float(szTemp);
}
}
stock Create_TE_LARGEFUNNEL(position[3], iSprite, flags){
message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
write_byte( TE_LARGEFUNNEL )
write_coord( position[0] ) // origin, x
write_coord( position[1] ) // origin, y
write_coord( position[2] ) // origin, z
write_short( iSprite ) // sprite (0 for none)
write_short( flags ) // 0 for collapsing, 1 for sending outward
message_end()
}
read_last_respawn_time(){
new fpath[256]
get_configsdir(fpath,255)
formatex(fpath,255,"%s%slast_respawn_time.ini",fpath,HLPresents_Dir)
new f = fopen(fpath,"r")
if(!f)
return get_systime()
new buffer[512],key[16],val[20]
while(!feof(f)){
fgets(f,buffer,511)
trim(buffer)
if(!strlen(buffer) || buffer[0] == ';')
continue
strtok(buffer,key,15,val,19,'=',1)
replace(val,19,"=","")
trim(key)
trim(val)
if(!strcmp(key,"last_respawn")){
fclose(f)
return str_to_num(val)
}
}
fclose(f)
return get_systime()
}
save_last_respawn_time(stTime){
new fpath[256]
get_configsdir(fpath,255)
formatex(fpath,255,"%s%slast_respawn_time.ini",fpath,HLPresents_Dir)
new f = fopen(fpath,"w+")
if(!f)
return
fprintf(f,";^n; %s v. %s^n; by %s
http://gf.hldm.org^n^n",PLUGIN,VERSION,AUTHOR)
fprintf(f,"last_respawn = %d^n^n",stTime)
fprintf(f,"; HLPresents, Copyright (c) 2013 AGHL.RU Dev Team")
fprintf(f,"^n;
http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community")
fclose(f)
}
stock get_view_pos( const id, Float:vViewPos[3] ){
new Float:vOfs[3]
pev( id, pev_origin, vViewPos )
pev( id, pev_view_ofs, vOfs )
vViewPos[0] += vOfs[0]
vViewPos[1] += vOfs[1]
vViewPos[2] += vOfs[2]
}
stock Float:vel_by_aim( id, speed = 1 ){
new Float:v1[3], Float:vBlah[3]
pev( id, pev_v_angle, v1 )
engfunc( EngFunc_AngleVectors, v1, v1, vBlah, vBlah )
v1[0] *= speed
v1[1] *= speed
v1[2] *= speed
return v1
}
stock get_aiment(id){
new target
new Float:orig[3], Float:ret[3]
get_view_pos( id, orig )
ret = vel_by_aim( id, 9999 )
ret[0] += orig[0]
ret[1] += orig[1]
ret[2] += orig[2]
target = fm_trace_line(id,orig,ret,ret)
new movetype
if( target && pev_valid( target ) )
{
movetype = pev( target, pev_movetype )
if( !( movetype == MOVETYPE_WALK || movetype == MOVETYPE_STEP || movetype == MOVETYPE_TOSS ) )
return 0
}
else
{
target = 0
new ent = fm_find_ent_in_sphere(-1,ret,10.0)
while( !target && ent > 0 )
{
movetype = pev( ent, pev_movetype )
if( ( movetype == MOVETYPE_WALK || movetype == MOVETYPE_STEP || movetype == MOVETYPE_TOSS )
&& ent != id )
target = ent
ent = fm_find_ent_in_sphere(ent,ret,10.0)
}
}
if(0<target<=get_maxplayers())
return 0
new classname[32]
pev(target,pev_classname,classname,31)
if(!strcmp(classname,present_classname))
return target
return 0
}