superspawns.inc
Original include source with line numbers.
| 1 | #if defined _superspawns_included |
| 2 | #endinput |
| 3 | #endif |
| 4 | #define _superspawns_included |
| 5 | |
| 6 | #include <amxmodx> |
| 7 | #include <amxmisc> |
| 8 | #include <fakemeta> |
| 9 | #include <engine> |
| 10 | #include <cellarray> |
| 11 | #include <xs> |
| 12 | |
| 13 | #define SS_VERSION "1.0" |
| 14 | #define SS_MIN_DISTANCE 500.0 |
| 15 | #define SS_MAX_LOOPS 100000 |
| 16 | |
| 17 | new Array:g_vecSsOrigins |
| 18 | new Array:g_vecSsSpawns |
| 19 | new Array:g_vecSsUsed |
| 20 | new Float:g_flSsMinDist |
| 21 | new g_iSsTime |
| 22 | |
| 23 | new const g_szStarts[][] = { "info_player_start", "info_player_deathmatch" } |
| 24 | new const Float:g_flOffsets[] = { 3500.0, 3500.0, 1500.0 } |
| 25 | |
| 26 | public SsInit(Float:mindist) |
| 27 | { |
| 28 | new cmd[32] |
| 29 | format(cmd, 15, "_ss_dump%c%c%c%c", random_num('A', 'Z'), random_num('A', 'Z'), random_num('A', 'Z'), random_num('A', 'Z')) |
| 30 | register_cvar("sv_superspawns", SS_VERSION, (FCVAR_SERVER|FCVAR_SPONLY)) |
| 31 | register_concmd(cmd, "SsDump") |
| 32 | |
| 33 | g_flSsMinDist = mindist |
| 34 | g_vecSsOrigins = ArrayCreate(3, 1) |
| 35 | g_vecSsSpawns = ArrayCreate(3, 1) |
| 36 | g_vecSsUsed = ArrayCreate(3, 1) |
| 37 | } |
| 38 | |
| 39 | stock SsClean() |
| 40 | { |
| 41 | g_flSsMinDist = 0.0 |
| 42 | ArrayClear(g_vecSsOrigins) |
| 43 | ArrayClear(g_vecSsSpawns) |
| 44 | ArrayClear(g_vecSsUsed) |
| 45 | } |
| 46 | |
| 47 | stock SsGetOrigin(Float:origin[3]) |
| 48 | { |
| 49 | new Float:data[3], size |
| 50 | new ok = 1 |
| 51 | |
| 52 | while((size = ArraySize(g_vecSsOrigins))) |
| 53 | { |
| 54 | new idx = random_num(0, size - 1) |
| 55 | |
| 56 | ArrayGetArray(g_vecSsOrigins, idx, origin) |
| 57 | |
| 58 | new used = ArraySize(g_vecSsUsed) |
| 59 | for(new i = 0; i < used; i++) |
| 60 | { |
| 61 | ok = 0 |
| 62 | ArrayGetArray(g_vecSsUsed, i, data) |
| 63 | if(get_distance_f(data, origin) >= g_flSsMinDist) |
| 64 | { |
| 65 | ok = 1 |
| 66 | break |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | ArrayDeleteItem(g_vecSsOrigins, idx) |
| 71 | if(ok) |
| 72 | { |
| 73 | ArrayPushArray(g_vecSsUsed, origin) |
| 74 | return true |
| 75 | } |
| 76 | } |
| 77 | return false |
| 78 | } |
| 79 | |
| 80 | public SsDump() |
| 81 | { |
| 82 | new Float:origin[3] |
| 83 | new count = ArraySize(g_vecSsOrigins) |
| 84 | server_print("-------------------------------------------------------") |
| 85 | for(new i = 0; i < count; i++) |
| 86 | { |
| 87 | ArrayGetArray(g_vecSsOrigins, i, origin) |
| 88 | server_print("Origin: %f %f %f", origin[0], origin[1], origin[2]) |
| 89 | } |
| 90 | server_print("-------------------------------------------------------") |
| 91 | server_print("Number of origins: %i", count) |
| 92 | server_print("Time: %i", g_iSsTime) |
| 93 | server_print("-------------------------------------------------------") |
| 94 | } |
| 95 | |
| 96 | public SsScan() |
| 97 | { |
| 98 | new start, Float:origin[3], starttime |
| 99 | starttime = get_systime() |
| 100 | for(start = 0; start < sizeof(g_szStarts); start++) |
| 101 | { |
| 102 | server_print("Searching for %s", g_szStarts[start]) |
| 103 | new ent |
| 104 | if((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", g_szStarts[start]))) |
| 105 | { |
| 106 | new counter |
| 107 | pev(ent, pev_origin, origin) |
| 108 | ArrayPushArray(g_vecSsSpawns, origin) |
| 109 | while(counter < SS_MAX_LOOPS) |
| 110 | { |
| 111 | counter = GetLocation(origin, counter) |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | g_iSsTime = get_systime() |
| 116 | g_iSsTime -= starttime |
| 117 | } |
| 118 | |
| 119 | GetLocation(Float:start[3], &counter) |
| 120 | { |
| 121 | new Float:end[3] |
| 122 | for(new i = 0; i < 3; i++) |
| 123 | { |
| 124 | end[i] += random_float(0.0 - g_flOffsets[i], g_flOffsets[i]) |
| 125 | } |
| 126 | |
| 127 | if(IsValid(start, end)) |
| 128 | { |
| 129 | start[0] = end[0] |
| 130 | start[1] = end[1] |
| 131 | start[2] = end[2] |
| 132 | ArrayPushArray(g_vecSsOrigins, end) |
| 133 | } |
| 134 | counter++ |
| 135 | return counter |
| 136 | } |
| 137 | |
| 138 | IsValid(Float:start[3], Float:end[3]) |
| 139 | { |
| 140 | SetFloor(end) |
| 141 | end[2] += 36.0 |
| 142 | new point = engfunc(EngFunc_PointContents, end) |
| 143 | if(point == CONTENTS_EMPTY) |
| 144 | { |
| 145 | if(CheckPoints(end) && CheckDistance(end) && CheckVisibility(start, end)) |
| 146 | { |
| 147 | if(!trace_hull(end, HULL_LARGE, -1)) |
| 148 | { |
| 149 | return true |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | return false |
| 154 | } |
| 155 | |
| 156 | CheckVisibility(Float:start[3], Float:end[3]) |
| 157 | { |
| 158 | new tr |
| 159 | engfunc(EngFunc_TraceLine, start, end, IGNORE_GLASS, -1, tr) |
| 160 | return (get_tr2(tr, TR_pHit) < 0) |
| 161 | } |
| 162 | |
| 163 | SetFloor(Float:start[3]) |
| 164 | { |
| 165 | new tr, Float:end[3] |
| 166 | end[0] = start[0] |
| 167 | end[1] = start[1] |
| 168 | end[2] = -99999.9 |
| 169 | engfunc(EngFunc_TraceLine, start, end, DONT_IGNORE_MONSTERS, -1, tr) |
| 170 | get_tr2(tr, TR_vecEndPos, start) |
| 171 | } |
| 172 | |
| 173 | CheckPoints(Float:origin[3]) |
| 174 | { |
| 175 | new Float:data[3], tr, point |
| 176 | data[0] = origin[0] |
| 177 | data[1] = origin[1] |
| 178 | data[2] = 99999.9 |
| 179 | engfunc(EngFunc_TraceLine, origin, data, DONT_IGNORE_MONSTERS, -1, tr) |
| 180 | get_tr2(tr, TR_vecEndPos, data) |
| 181 | point = engfunc(EngFunc_PointContents, data) |
| 182 | if(point == CONTENTS_SKY && get_distance_f(origin, data) < 250.0) |
| 183 | { |
| 184 | return false |
| 185 | } |
| 186 | data[2] = -99999.9 |
| 187 | engfunc(EngFunc_TraceLine, origin, data, DONT_IGNORE_MONSTERS, -1, tr) |
| 188 | get_tr2(tr, TR_vecEndPos, data) |
| 189 | point = engfunc(EngFunc_PointContents, data) |
| 190 | if(point < CONTENTS_SOLID) |
| 191 | return false |
| 192 | |
| 193 | return true |
| 194 | } |
| 195 | |
| 196 | CheckDistance(Float:origin[3]) |
| 197 | { |
| 198 | new Float:dist, Float:data[3] |
| 199 | new count = ArraySize(g_vecSsSpawns) |
| 200 | for(new i = 0; i < count; i++) |
| 201 | { |
| 202 | ArrayGetArray(g_vecSsSpawns, i, data) |
| 203 | dist = get_distance_f(origin, data) |
| 204 | if(dist < SS_MIN_DISTANCE) |
| 205 | return false |
| 206 | } |
| 207 | |
| 208 | count = ArraySize(g_vecSsOrigins) |
| 209 | for(new i = 0; i < count; i++) |
| 210 | { |
| 211 | ArrayGetArray(g_vecSsOrigins, i, data) |
| 212 | dist = get_distance_f(origin, data) |
| 213 | if(dist < SS_MIN_DISTANCE) |
| 214 | return false |
| 215 | } |
| 216 | |
| 217 | return true |
| 218 | } |
| 219 | |