#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta>
#include <fun>
#include <hamsandwich>
#include <mapname_patcher>
#define PLUGIN "[CSO] Challenge"
#define VERSION "1.0"
#define AUTHOR "RaZzoR"
#define DICTIONARY "cso_challenge.txt"
#define USE_CSO_SKINS
#if defined USE_CSO_SKINS
new const chall_new_v_models[][][] = {
{ "models/v_knife.mdl", "models/cso_challenge/v_knife.mdl" }
}
#endif
new const allow_maps[][][] = {
{ "cso_jump1", "Jump 1" },
{ "cso_jump2", "Jump 2" },
{ "cso_run1", "Run 1" },
{ "cso_run2", "Run 2" }
}
new const entity_hook[][][] = {
{ "chall_start", "func_buyzone" },
{ "chall_check0", "func_bomb_target" },
{ "chall_check1", "func_hostage_rescue" },
{ "chall_check2", "func_vip_safetyzone" },
{ "chall_finish", "func_escapezone" },
{ "chall_return", "func_wall" }
}
new const objective_icons[][] = {
"c4",
"buyzone",
"rescue",
"escape",
"vipsafety"
}
new const chall_sounds[][]= {
"cso_challenge/cm_check.wav",
"cso_challenge/cm_down.wav",
"cso_challenge/cm_goal.wav",
"cso_challenge/cm_start.wav",
"cso_challenge/task_complete.wav"
}
new const chall_blockmsgs[][] = {
"#Terrorist_Escaped",
"#Terrorists_Escaped",
"#Hint_ct_vip_zone",
"#Hint_hostage_rescue_zone",
"#Hint_you_are_in_targetzone",
"#Hint_you_are_the_vip",
"#Hint_you_have_the_bomb",
"#Hint_terrorist_vip_zone",
"#Hint_terrorist_escape_zone"
}
new const challenge_gamename[] = "Challenge"
new const chall_bgsound[] = "sound/cso_challenge/chall_ambience.mp3"
new bool:ch_touched_ent_start[33], bool:ch_touched_ent_check0[33], bool:ch_touched_ent_check1[33], bool:ch_touched_ent_check2[33], bool:ch_touched_ent_finish[33], bool:ch_touched_ent_return[33]
new Float:ch_save_timer[33][5], Float:ch_timer[33], Float:get_player_time[33], Float:ch_delay
new ch_semiclip[33], ch_origin[3], ch_plr_origin[33][3], random_map
/* ch_save_timer[0][0] = save 1st checkpoint (top1)
ch_save_timer[0][1] = save 2nd checkpoint (top1)
ch_save_timer[0][2] = save 3rd checkpoint (top1)
ch_save_timer[index][3] = save best time (top1, top2, top3)
ch_save_timer[index][4] = save best time (player)
*/
public plugin_init() {
register_dictionary(DICTIONARY)
new map_name[32], buffer[128], index
get_mapname(map_name, 31)
for(index=0;index<sizeof(allow_maps);index++) {
if(equal(map_name, allow_maps[index][0])) {
if(strlen(allow_maps[index][1]) > 0)
Patch_MapName(allow_maps[index][1])
break
}
}
if(index == sizeof(allow_maps)) {
formatex(buffer, sizeof(buffer), "%L", LANG_SERVER, "CHALL_WRONG_MAP")
set_fail_state(buffer)
return
}
register_plugin(PLUGIN, VERSION, AUTHOR)
register_message(get_user_msgid("StatusIcon"), "msgStatusIcon")
register_message(get_user_msgid("RoundTime"), "msgRoundTime")
register_message(get_user_msgid("HideWeapon"), "msgHideWeapon")
register_message(get_user_msgid("Money"), "msgMoney")
register_message(get_user_msgid("TextMsg"), "msgTextMsg")
register_clcmd("chooseteam", "block_cmd")
RegisterHam(Ham_TraceAttack, "player", "HamTraceAttack_Pre")
RegisterHam(Ham_Spawn, "player", "Spawn", 1)
register_forward(FM_StartFrame, "fwStartFrame", 0)
register_forward(FM_AddToFullPack, "fwFullPack", 1)
register_forward(FM_ClientKill, "Forward_ClientKill")
register_forward(FM_GetGameDescription, "GameDesc")
for(new i=0;i<sizeof(entity_hook);i++) {
new buffer[128]
formatex(buffer, sizeof(buffer), "hook_%s", entity_hook[i][0])
register_touch(entity_hook[i][0], "player", buffer)
}
register_event("ResetHUD", "onResetHUD", "b")
register_event("DeathMsg", "death", "a")
#if defined USE_CSO_SKINS
register_event("CurWeapon","Weapon_Hook","be","1=1")
#endif
random_map = random(sizeof(allow_maps))
}
public plugin_cfg()
server_cmd("sv_restart 1")
public plugin_precache() {
for(new i=0;i<sizeof(chall_new_v_models);i++)
precache_model(chall_new_v_models[i][1])
for(new i=0;i<sizeof(chall_sounds);i++)
precache_sound(chall_sounds[i])
precache_generic(chall_bgsound)
}
#if defined USE_CSO_SKINS
public Weapon_Hook(id) {
if(!is_user_alive(id))
return PLUGIN_CONTINUE
static model[32]
pev(id, pev_viewmodel2, model, 31)
for(new i=0;i<sizeof(chall_new_v_models);i++) {
if(equali(model, chall_new_v_models[i][0])) {
set_pev(id, pev_viewmodel2, chall_new_v_models[i][1])
break
}
}
return PLUGIN_CONTINUE
}
#endif
public block_cmd(id)
return PLUGIN_HANDLED
public Forward_ClientKill(id)
return FMRES_SUPERCEDE
public GameDesc() {
forward_return(FMV_STRING, challenge_gamename)
return FMRES_SUPERCEDE
}
public onResetHUD(id) {
if(!is_user_connected(id))
return
message_begin(MSG_ONE, get_user_msgid("HideWeapon"), _, id)
write_byte((1<<5))
message_end()
}
public msgRoundTime(const MsgId, const MsgDest, const MsgEnt)
set_msg_arg_int(1, ARG_SHORT, get_timeleft())
public msgHideWeapon()
set_msg_arg_int(1, ARG_BYTE, get_msg_arg_int(1) | (1<<5))
public msgMoney(msgid, dest, id) {
set_pdata_int(id, 115, 0)
set_msg_arg_int(1, ARG_LONG, 0)
}
public msgTextMsg(msg_id, msg_dest, msg_entity) {
static message[32]
get_msg_arg_string(2, message, charsmax(message))
for(new i=0; i < sizeof(chall_blockmsgs); i++) {
if(equal(message, chall_blockmsgs[i]))
return PLUGIN_HANDLED
}
return PLUGIN_CONTINUE
}
public msgStatusIcon(msgid, msgdest, id) {
static szIcon[11]
get_msg_arg_string(2, szIcon, 10)
for(new i=0;i<sizeof(objective_icons);i++) {
if(equal(szIcon, objective_icons[i]) && get_msg_arg_int(1)) {
set_pdata_int(id, 235, get_pdata_int(id, 235) & ~(1<<0))
return PLUGIN_HANDLED
}
}
return PLUGIN_CONTINUE
}
public HamTraceAttack_Pre(iVictim, iAttacker, Float:flDamage, Float:fVecDir[3], tr)
return HAM_IGNORED
public map_change()
server_cmd("changelevel %s", allow_maps[random_map][0])
public client_disconnect(id) {
ch_timer[id] = 0.0
get_player_time[id] = 0.0
remove(id)
client_cmd(id, "mp3 stop")
}
public client_putinserver(id) {
if(is_user_bot(id)) {
new buffer[128]
formatex(buffer, sizeof(buffer), "%L", LANG_SERVER, "CHALL_BOT")
set_fail_state(buffer)
return
}
set_task(0.1, "play_bg_sound", id)
}
public play_bg_sound(id) {
client_cmd(id, "mp3 play %s", chall_bgsound)
set_task(234.0, "play_bg_sound", id)
}
public pfn_keyvalue(entid) {
new classname[32], key[32], value[32]
copy_keyvalue(classname, 31, key, 31, value, 31)
for(new i=0;i<sizeof(entity_hook);i++) {
if(equal(key, "classname") && equal(value, entity_hook[i][0]))
DispatchKeyValue("classname", entity_hook[i][1])
}
for(new i=0;i<sizeof(entity_hook);i++) {
if(equal(classname, entity_hook[i][1])) {
entity_set_string(entid, EV_SZ_classname, entity_hook[i][0])
set_entity_visibility(entid, 0)
}
}
}
public fwFullPack(es, e, ent, host, flags, player, pSet) {
if(player && ch_semiclip[ent] && ch_semiclip[host]) {
static Float:flDistance
flDistance = entity_range(host, ent)
set_es(es, ES_Solid, SOLID_NOT)
set_es(es, ES_RenderMode, kRenderTransAlpha)
set_es(es, ES_RenderAmt, floatround(flDistance * 1.5))
}
return FMRES_IGNORED
}
public fwStartFrame(id) {
static iPlayers[32], iNum, iPlayer, iPlayer2
get_players(iPlayers, iNum)
arrayset(ch_semiclip, 0, sizeof(ch_semiclip))
for(new i=0;i<iNum; i++) {
iPlayer = iPlayers[i]
if(!is_user_alive(iPlayer))
continue
for(new j=0;j<iNum;j++) {
iPlayer2 = iPlayers[j]
if(iPlayer == iPlayer2 || !is_user_alive(iPlayer2))
continue
static Float:vOrigin1[3], Float:vOrigin2[3]
pev(iPlayer, pev_origin, vOrigin1)
pev(iPlayer2, pev_origin, vOrigin2)
if(vector_distance(vOrigin1, vOrigin2) < 96) {
ch_semiclip[iPlayer] = true
ch_semiclip[iPlayer2] = true
}
}
}
for(new i=0;i<iNum; i++) {
iPlayer = iPlayers[i]
if(is_user_alive(iPlayer))
set_pev(iPlayer, pev_solid, ch_semiclip[iPlayer] ? SOLID_NOT : SOLID_SLIDEBOX)
}
return FMRES_IGNORED
}
public death() {
new victim = read_data(2)
set_task(0.1, "spawn_plr", victim)
}
public spawn_plr(id) {
ExecuteHamB(Ham_CS_RoundRespawn, id)
ch_origin[0] = ch_plr_origin[id][0]
ch_origin[1] = ch_plr_origin[id][1]
ch_origin[2] = ch_plr_origin[id][2] + 10
set_user_origin(id, ch_origin)
}
public Spawn(id) {
if(!is_user_connected(id)) return
new weapon_name[15]
switch(get_user_team(id)) {
case 1: weapon_name = "weapon_glock18"
case 2: weapon_name = "weapon_usp"
default: return
}
new weapon = find_ent_by_owner(-1, weapon_name, id)
if(!weapon) return
engclient_cmd(id, "drop", weapon_name)
new weaponbox = entity_get_edict(weapon, EV_ENT_owner)
if(!weaponbox || weaponbox == id) return
remove_entity(weaponbox)
remove_entity(weapon)
}
public client_PostThink(id) {
/* Check Timeleft */
if(get_timeleft() <= 0) {
client_print(0, print_center, "%L: %s", LANG_PLAYER, "CHALL_TIMERUP", strlen(allow_maps[random_map][1]) > 0 ? allow_maps[random_map][1] : allow_maps[random_map][0])
set_task(1.0, "map_change")
}
/* Player Info(s)*/
new Plr_Time[15], TimeTOP[15]
TOPtimesToString((ch_timer[id] == 0.0 ? get_player_time[id] : get_gametime() - ch_timer[id] - ch_delay), Plr_Time, 14)
TOPtimesToString((ch_save_timer[id][4] - ch_delay), TimeTOP, 14)
set_hudmessage(255, 255, 255, -1.00, 0.00, 0, 6.0, 12.0, 0.1, 0.2, -1)
show_hudmessage(id, "%s^n^n[%L]^n%s", Plr_Time, id, "CHALL_TOPSCORE", TimeTOP)
/* TOP3 HUD */
new players[32], num, top1, top2, top3
new top1_name[33], top2_name[33], top3_name[33], TimeTOP1[15], TimeTOP2[15], TimeTOP3[15]
get_players(players, num)
SortCustom1D(players, num, "sort_bestplayer")
top1 = players[0]
top2 = players[1]
top3 = players[2]
if(ch_save_timer[top1][3] > 1) {
get_user_name(top1, top1_name, charsmax(top1_name))
TOPtimesToString((ch_save_timer[top1][3] - ch_delay), TimeTOP1, 14)
}
if(ch_save_timer[top2][3] > 1) {
get_user_name(top2, top2_name, charsmax(top2_name))
TOPtimesToString((ch_save_timer[top2][3] - ch_delay), TimeTOP2, 14)
}
if(ch_save_timer[top3][3] > 1) {
get_user_name(top3, top3_name, charsmax(top3_name))
TOPtimesToString((ch_save_timer[top3][3] - ch_delay), TimeTOP3, 14)
}
set_hudmessage(255, 153, 0, -0.00, 0.21, 0, 6.0, 12.0, 0.1, 0.2, -1)
show_hudmessage(0, "[%L] %s^n%s^n^n[%L] %s^n%s^n^n[%L] %s^n%s", LANG_PLAYER, "CHALL_1ST", top1_name, TimeTOP1, LANG_PLAYER, "CHALL_2ND", top2_name, TimeTOP2, LANG_PLAYER, "CHALL_3RD", top3_name, TimeTOP3)
}
public hook_chall_start(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_start[id]) {
ch_touched_ent_start[id] = true
get_user_origin(id, ch_origin, 0)
ch_plr_origin[id][0] = ch_origin[0]
ch_plr_origin[id][1] = ch_origin[1]
ch_plr_origin[id][2] = ch_origin[2]
ch_timer[id] = get_gametime()
client_cmd(id, "spk ^"%s^"", chall_sounds[3])
client_print(id, print_center, "%L", id, "CHALL_GOGOGO")
}
}
public hook_chall_check0(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_check0[id]) {
ch_touched_ent_check0[id] = true
get_user_origin(id, ch_origin, 0)
ch_plr_origin[id][0] = ch_origin[0]
ch_plr_origin[id][1] = ch_origin[1]
ch_plr_origin[id][2] = ch_origin[2]
client_cmd(id, "spk ^"%s^"", chall_sounds[0])
new minutes = floatround((get_gametime() - ch_timer[id] - ch_delay) / 60, floatround_floor)
new seconds = floatround((get_gametime() - ch_timer[id] - ch_delay) - minutes * 60, floatround_floor)
new miliseconds = floatround(((get_gametime() - ch_timer[id] - ch_delay) - (minutes * 60 + seconds)) * 100, floatround_floor)
get_player_time[id] = (minutes * 60.0) + (seconds * 1.0) + (miliseconds / 100.0)
if(get_player_time[id] < ch_save_timer[0][0] || ch_save_timer[0][0] < 1) {
new TimeBetter[15]
TOPtimesToString((ch_save_timer[0][0] < 1 ? 0.0 : ch_save_timer[0][0] - get_player_time[id] - ch_delay), TimeBetter, 14)
client_print(id, print_center, "%L -%s %L", id, "CHALL_CHECKPTS", TimeBetter, id, "CHALL_BESTREC")
ch_save_timer[0][0] = get_player_time[id]
}
else {
new TimeMore[15]
TOPtimesToString((get_player_time[id] - ch_save_timer[0][0] - ch_delay), TimeMore, 14)
client_print(id, print_center, "%L +%s", id, "CHALL_CHECKPTS", TimeMore)
}
}
}
public hook_chall_check1(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_check1[id]) {
ch_touched_ent_check1[id] = true
get_user_origin(id, ch_origin, 0)
ch_plr_origin[id][0] = ch_origin[0]
ch_plr_origin[id][1] = ch_origin[1]
ch_plr_origin[id][2] = ch_origin[2]
client_cmd(id, "spk ^"%s^"", chall_sounds[0])
new minutes = floatround((get_gametime() - ch_timer[id] - ch_delay) / 60, floatround_floor)
new seconds = floatround((get_gametime() - ch_timer[id] - ch_delay) - minutes * 60, floatround_floor)
new miliseconds = floatround(((get_gametime() - ch_timer[id] - ch_delay) - (minutes * 60 + seconds)) * 100, floatround_floor)
get_player_time[id] = (minutes * 60.0) + (seconds * 1.0) + (miliseconds / 100.0)
if(get_player_time[id] < ch_save_timer[0][1] || ch_save_timer[0][1] < 1) {
new TimeBetter[15]
TOPtimesToString((ch_save_timer[0][1] < 1 ? 0.0 : ch_save_timer[0][1] - get_player_time[id] - ch_delay), TimeBetter, 14)
client_print(id, print_center, "%L -%s %L", id, "CHALL_CHECKPTS", TimeBetter, id, "CHALL_BESTREC")
ch_save_timer[0][1] = get_player_time[id]
}
else {
new TimeMore[15]
TOPtimesToString((get_player_time[id] - ch_save_timer[0][1] - ch_delay), TimeMore, 14)
client_print(id, print_center, "%L +%s", id, "CHALL_CHECKPTS", TimeMore)
}
}
}
public hook_chall_check2(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_check2[id]) {
ch_touched_ent_check2[id] = true
get_user_origin(id, ch_origin, 0)
ch_plr_origin[id][0] = ch_origin[0]
ch_plr_origin[id][1] = ch_origin[1]
ch_plr_origin[id][2] = ch_origin[2]
client_cmd(id, "spk ^"%s^"", chall_sounds[0])
new minutes = floatround((get_gametime() - ch_timer[id] - ch_delay) / 60, floatround_floor)
new seconds = floatround((get_gametime() - ch_timer[id] - ch_delay) - minutes * 60, floatround_floor)
new miliseconds = floatround(((get_gametime() - ch_timer[id] - ch_delay) - (minutes * 60 + seconds)) * 100, floatround_floor)
get_player_time[id] = (minutes * 60.0) + (seconds * 1.0) + (miliseconds / 100.0)
if(get_player_time[id] < ch_save_timer[0][2] || ch_save_timer[0][2] < 1) {
new TimeBetter[15]
TOPtimesToString((ch_save_timer[0][2] < 1 ? 0.0 : ch_save_timer[0][2] - get_player_time[id] - ch_delay), TimeBetter, 14)
client_print(id, print_center, "%L -%s %L", id, "CHALL_CHECKPTS", TimeBetter, id, "CHALL_BESTREC")
ch_save_timer[0][2] = get_player_time[id]
}
else {
new TimeMore[15]
TOPtimesToString((get_player_time[id] - ch_save_timer[0][2] - ch_delay), TimeMore, 14)
client_print(id, print_center, "%L +%s", id, "CHALL_CHECKPTS", TimeMore)
}
}
}
public hook_chall_finish(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_finish[id]) {
ch_touched_ent_finish[id] = true
new minutes = floatround((get_gametime() - ch_timer[id] - ch_delay) / 60, floatround_floor)
new seconds = floatround((get_gametime() - ch_timer[id] - ch_delay) - minutes * 60, floatround_floor)
new miliseconds = floatround(((get_gametime() - ch_timer[id] - ch_delay) - (minutes * 60 + seconds)) * 100, floatround_floor)
new players[32], num, top1, top2, top3, tempid
get_players(players, num)
SortCustom1D(players, num, "sort_bestplayer")
top1 = players[0]
top2 = players[1]
top3 = players[2]
if(ch_save_timer[top1][3] < 1)
top1 = 0
if(ch_save_timer[top2][3] < 1)
top2 = 0
if(ch_save_timer[top3][3] < 1)
top3 = 0
get_player_time[id] = (minutes * 60.0) + (seconds * 1.0) + (miliseconds / 100.0)
if(get_player_time[id] < ch_save_timer[top1][3] || (ch_save_timer[id][3] < 1 && ch_save_timer[top1][3] < 1)) {
for(new i=0;i<num;i++) {
tempid = players[i]
if(tempid != id) {
client_cmd(tempid, "spk ^"%s^"", chall_sounds[1])
client_print(tempid, print_center, "%L", id, "CHALL_RANK")
}
}
if(id == top1) {
client_cmd(id, "spk ^"%s^"", chall_sounds[2])
client_print(id, print_center, "%L", id, "CHALL_FINISH")
}
else {
client_cmd(id, "spk ^"%s^"", chall_sounds[4])
client_print(id, print_center, "%L", id, "CHALL_ACH_1ST")
}
ch_save_timer[id][3] = get_player_time[id]
}
else if(get_player_time[id] < ch_save_timer[top2][3] || (ch_save_timer[id][3] < 1 && ch_save_timer[top2][3] < 1)) {
for(new i=0;i<num;i++) {
tempid = players[i]
if(tempid != id) {
client_cmd(tempid, "spk ^"%s^"", chall_sounds[1])
client_print(tempid, print_center, "%L", id, "CHALL_RANK")
}
}
if(id == top2) {
client_cmd(id, "spk ^"%s^"", chall_sounds[2])
client_print(id, print_center, "%L", id, "CHALL_FINISH")
}
else {
client_cmd(id, "spk ^"%s^"", chall_sounds[4])
client_print(id, print_center, "%L", id, "CHALL_ACH_2ND")
}
ch_save_timer[id][3] = get_player_time[id]
}
else if(get_player_time[id] < ch_save_timer[top3][3] || (ch_save_timer[id][3] < 1 && ch_save_timer[top3][3] < 1)) {
for(new i=0;i<num;i++) {
tempid = players[i]
if(tempid != id) {
client_cmd(tempid, "spk ^"%s^"", chall_sounds[1])
client_print(tempid, print_center, "%L", id, "CHALL_RANK")
}
}
if(id == top3) {
client_cmd(id, "spk ^"%s^"", chall_sounds[2])
client_print(id, print_center, "%L", id, "CHALL_FINISH")
}
else {
client_cmd(id, "spk ^"%s^"", chall_sounds[4])
client_print(id, print_center, "%L", id, "CHALL_ACH_3RD")
}
ch_save_timer[id][3] = get_player_time[id]
}
else {
client_cmd(id, "spk ^"%s^"", chall_sounds[2])
client_print(id, print_center, "%L", id, "CHALL_FINISH")
}
if(get_player_time[id] < ch_save_timer[id][4] || ch_save_timer[id][4] < 1)
ch_save_timer[id][4] = get_player_time[id]
ch_timer[id] = 0.0
new frags = get_user_frags(id) + 1
set_user_frags(id, frags)
message_begin(MSG_ALL, get_user_msgid("ScoreInfo"))
write_byte(id)
write_short(frags)
write_short(get_user_deaths(id))
write_short(0)
write_short(get_user_team(id))
message_end()
}
}
public hook_chall_return(ent, id) {
if(is_user_alive(id) && !ch_touched_ent_return[id]) {
ch_touched_ent_return[id] = true
ExecuteHamB(Ham_CS_RoundRespawn, id)
remove(id)
get_player_time[id] = 0.0
}
}
public sort_bestplayer(id1, id2) {
if(ch_save_timer[id1][3] < ch_save_timer[id2][3]) {
if(ch_save_timer[id1][3] < 1 || ch_save_timer[id2][3] < 1) return 1
return -1
}
else if(ch_save_timer[id1][3] > ch_save_timer[id2][3] ) {
if(ch_save_timer[id1][3] < 1 || ch_save_timer[id2][3] < 1) return -1
return 1
}
return 0
}
remove(id) {
ch_touched_ent_start[id] = false
ch_touched_ent_check0[id] = false
ch_touched_ent_check1[id] = false
ch_touched_ent_check2[id] = false
ch_touched_ent_finish[id] = false
ch_touched_ent_return[id] = false
}
TOPtimesToString(const Float:top, szOutPut[], const iLen) {
new iMinutes = floatround(top / 60.0, floatround_floor)
new iSeconds = floatround(top - iMinutes * 60, floatround_floor)
new iMiliSeconds = floatround((top - (iMinutes * 60 + iSeconds)) * 100, floatround_floor)
formatex(szOutPut, iLen, "%02i:%02i:%02i", iMinutes, iSeconds, iMiliSeconds)
}