standalone Anti Camper Mod

Nightwing
So, hab mir mit meinem Lieblings Scripter die Nacht um die Ohren geschlagen (DANKE) und stelle jetzt einen echten standalone Anti Camper Mod vor Freude

FEATURES

- Camper wird auf dem Kompass markiert und furzt zusätzlich gelb
- Unterscheidung, ob jemand eine Sniperwaffe hat, oder nicht.
- Einzelne Maps / Gametypes können ohne Anticamperoption geladen werden, einstellbar in der Config


Und los:

Folgende Dateien benötigt der Mod, zu Beziehen siehe Download unten:

- fx\fart\fartsmoke.efx
- sound\custom\fart.mp3
- soundalias\iw_generic2.csv
- localisedstrings\camping.str

In die soundalias kommt folgender Inhalt rein, wir wollen den Camper ja Furzen lassen:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
#Dialog_generic - All the dialog called automaticall from animscripts.,,

"# If the text in the first column of a row starts with a # character, the row is ignored",,"If the first column for a row is blank, then the row is ignored"
,"If the first column for a row is blank, then the row is ignored",
# The first non-comment line of a sound alias file specifies the key name for all values appearing in this column.,,
"# This means it is safe to swap entire columns around, though you should never swap partial columns.",,
"# You can invent new keys, but the game will ignore them if it doesn't know about them.",,
"# You can leave out keys, but the ""name"" and ""file"" keys must always be present.",,

,name,name of the alias that is used to play this sound (required)
,sequence,"used to uniquely identify alias entries when more than one sound goes to an alias, used only to catch unwanted duplicates (default = 0)"
,file,the name of the file that contains the sound data (required)
,vol_min,"0 is silent, 1 is full volume (default = 1)"
,vol_max,"0 is silent, 1 is full volume (default = same as vol_min)"
,vol_mod,"blank causes no effect on vol_min and vol_max, otherwise the string must match a string in the volumemodgroups.def file and the value in that file corresponding to that string will be used to adjust vol_min and vol_max, clamped to the valid range"
,pitch_min,"1 is normal playback, 2 is twice as fast, 0.5 is half as fast (default = 1)"
,pitch_max,"1 is normal playback, 2 is twice as fast, 0.5 is half as fast (default = same as pitch_min)"
,dist_min,"within this distance in inches, the sound is always full volume (default = 120)"
,dist_max,"outside this distance in inches, the sound is not started.  If left blank or set to 0, the sound will play from any distance.  This does not affect sound volume falloff."
,channel,"auto, menu, weapon, voice, item, body, local, music, announcer (default = auto)"
,type,primed (a streamed sound which gets primed on some platforms) / streamed / loaded (default = loaded)
,probability,weight to use for the weighted probability of playing this sound instead of another sound (default = 1)
,loop,"whether this sound is ""looping"" or ""nonlooping"" (default = ""nonlooping"")"
,masterslave,"if ""master"", this is a master sound.  If a number, then this sound's volume will be multiplied by that number (a percentage between 0 and 1) any master sound is playing.  If blank, then neither master nor slave."
,loadspec,"space-separated list of which maps should use this alias; eg, ""burnville dawnville"".  If blank, the alias is used on all maps."
,compression,"a string corresponding to an entry in ""XMAUpdate.tbl"" which is used to determine compression by XMAUpdate.exe"
,secondaryaliasname,"defined the name of an additional sound alias to play in addition to the current alias being played. Note that it is an error for the secondaryalias to also define a secondaryaliasname (eg, if B is a secondaryalias of A, B is not allowed to have its own secondaryalias)."
,volumefalloffcurve,if blank uses the linear curve which can not be changed. A string 'XXXX' corresponds to the curve defined by the file 'soundaliases/XXXX.vfcurve'
,startdelay,defaults to no delay. The value is the number of milliseconds to delay starting the sound by
,speakermap,if blank uses the default speakermappings which cannot be changed. A string 'XXXX' corresponds to the speakermap defined by the file 'soundaliases/XXXX.spkrmap'. 
,reverb,"blank means the alias is affected normally by wet and dry levels, ""fulldrylevel"" forces the alias to use a full drylevel (ignoring the global drylevel), ""nowetlevel"" forces the alias to use no wetlevel (ignoring the global wetlevel)"
,lfe percentage,this determines what percentage of the highest calculated spatialized speaker volume should be passed to the LFE. blank means no LFE for the sound

name,sequence,probability,file,vol_min,vol_max,vol_mod,pitch_min,pitch_max,dist_min,dist_max,channel,type,loop,masterslave,loadspec,subtitle,compression,secondaryaliasname,volumefalloffcurve,startdelay,speakermap,reverb,lfe percentage

# Camper

fart,,,custom/fart.mp3,1,1,,,,1000000,,auto,streamed

##END OF FILE,,,,,,,,,,,,,,,,,,,




In die localisedstrings\camping.gsc kommt das rein, frei nach Belieben editierbar:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
REFERENCE			WARNING_MESSAGE_SELF
LANG_ENGLISH		"^5Beweg Dich &&1^5, nicht Campen!"

REFERENCE			MARKED_MESSAGE_SELF
LANG_ENGLISH		"&&1^5, Du wirst für's Campen markiert"

REFERENCE			MARKED_MESSAGE_ALL
LANG_ENGLISH		"&&1^5 wird wegen Camping markiert!"

REFERENCE			TIME_MESSAGE_SELF
LANG_ENGLISH		"^5dies wird für &&1^5 Sekunden anhalten..."

REFERENCE			TIME_MESSAGE_ALL
LANG_ENGLISH		"^5für &&1^5 Sekunden..."

REFERENCE			SURVIVED_MESSAGE_SELF
LANG_ENGLISH		"^5Nochmal Glück gehabt &&1^5, Du hast die Bestrafung überlebt!"

REFERENCE			SURVIVED_MESSAGE_ALL
LANG_ENGLISH		"&&1^5 hat die Bestrafung überlebt!"

REFERENCE			DIED_MESSAGE_SELF
LANG_ENGLISH		"&&1^5, bewegst Du Dich bei der nächsten Warnung?"

REFERENCE			DIED_MESSAGE_ALL
LANG_ENGLISH		"&&1^5 hat die Bestrafung nicht überlebt!"

ENDMARKER



Nun ändern wir im Serverseitigen Teil folgendes an allen Gametypes, hier ein Beispiel anhand der maps\mp\gametypes\dm.gsc:

Am Ende der Funktion main() folgendes hinzu:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
/// ** Variables for the OO StandAlonCamperMod ** ///
	maps\mp\gametypes\_camping::Variables();



Weiter unten, am Ende der Funktion Callback_StartGameType() noch folgendes hinzufügen:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
3:
/// ** Launch the OO StandAlonCamperMod ** ///
	thread maps\mp\gametypes\_camping::main();



Nun erstellen wir im Ordner maps\mp\gametypes ein neues .gsc File, das den Namen _camping.gsc trägt und füttern es mit folgendem Inhalt:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
//  **  *************************************************************************************************  **  //
//	**		OO StandAlonCamperMod 	© Olle Otze		contact theodyn@arcor.de     www.HellZone-am.de		   **  //
//  **  *************************************************************************************************  **  //

/*  *****************************************************************************************************  **  //
	
	Filelocation of gametypes: maps\mp\gametypes\
	
	The next 2 lines u must paste at the end of the funktion main() in your gametype (dm.gsc, tdm.gsc, sd.gsc,...)
	
/// ** Variables for the OO StandAlonCamperMod ** ///
	maps\mp\gametypes\_camping::Variables();



	The next 2 lines u must paste at the end of the funktion Callback_StartGameType() in your gametype (dm.gsc, tdm.gsc, sd.gsc,...)

/// ** Launch the OO StandAlonCamperMod ** ///
	thread maps\mp\gametypes\_camping::main();

	This file (_camping.gsc) must be located in the same place like u gametypfiles: maps\mp\gametypes\

*/// ****************************************************************************************************  **


Variables(){	

	//get cvar
	level.no_camper	= cvardef("no_camper", "", "", "","string");
	level.campwarntime = cvardef("campwarntime", 0, 0, 300, "int");
	level.campobjtime = cvardef("campobjtime", level.campwarntime+10, level.campwarntime+5, 600, "int");
	level.camptimer = cvardef("camptimer", 20, 0, 300, "int");
	level.campsniper_warntime = cvardef("campsniper_warntime", 0, 0, 600, "int");
	level.campsniper_objtime = cvardef("campsniper_objtime", level.campsniper_warntime+10, level.campsniper_warntime+5, 1200, "int");
	
	
	//Load fx effects
	level.effect["fartbomb"] = loadfx("fx/fart/fartsmoke.efx");
	
	//precache
	level thread Precache();
	
	//set variables
	level.iscamper = false;
}

cvardef(varname, vardefault, min, max, type){

	mapname = getcvar("mapname");
	gametype = getcvar("g_gametype");
	multigtmap = gametype + "_" + mapname;

	tempvar = varname + "_" + gametype;
	if(getcvar(tempvar) != "") varname = tempvar;

	tempvar = varname + "_" + mapname;
	if(getcvar(tempvar) != "") varname = tempvar;

	tempvar = varname + "_" + multigtmap;
	if(getcvar(tempvar) != "") varname = tempvar;


	switch(type){
	
		case "int":
		if(getcvar(varname) == "") definition = vardefault;
		else definition = getcvarint(varname);
		break;
		
		case "float":
		if(getcvar(varname) == "") definition = vardefault;
		else definition = getcvarfloat(varname);
		break;
		
		case "string":
		default:
		if(getcvar(varname) == "") definition = vardefault;
		else definition = getcvar(varname);
		break;
	}

	if(type != "string"){
	
		
		if(min != 0 && definition < min) definition = min;
		else if(max != 0 && definition > max) definition = max;
	}

	return definition;
}

Precache(){

	precacheShader("objpoint_radio");
	precacheShader("field_radio");
}

main(){

	//start standalone
	level thread onPlayerConnect();
	
	level PrecacheTeamBased();	
}

PrecacheTeamBased(){

	switch(game["allies"]){
		
		case "american":	precacheShader("objective_american"); break;
		case "british":		precacheShader("objective_british"); break;
		default:			precacheShader("objective_russian"); break;
	}

	precacheShader("objective_german");
}

onPlayerConnect(){

	self endon("disconnect");

	if(getcvar("mapname") == level.no_camper) return;
	if(getcvar("g_gametype") == level.no_camper) return;

	
	for(;;){
	
		level waittill("connecting", player);
		
		player thread onJoinedTeam();
		player thread onPlayerKilled();
	}
}

onJoinedTeam(){

	self endon("disconnect");
	
	for(;;){
	
		self waittill("joined_team");
		
		self thread CheckCamping();
	}
}

onPlayerKilled(){

	self endon("disconnect");
	
	for(;;){
	
		self waittill("killed_player");
		
		self thread MessageCamperDied();
	}
}

CheckCamping(){

	level endon("round_ended");
	self endon("disconnect");
	
	campingtime = 0;
	snipercampingtime = 0;
	show_warning = false;

	for(;;){
	
		wait 0.5;
		if(level.iscamper) continue;
		
		startpos = self.origin;
		wait 0.5;
		endpos = self.origin;
		
		if(WeaponType(self getcurrentweapon(),"sniper")){
		
			if(level.campsniper_warntime){
			
					if(distance(startpos, endpos) < 20) snipercampingtime++;
						else snipercampingtime = 0;
					
					if(snipercampingtime == level.campsniper_warntime)
						show_warning = true;
			}
			
			else continue;
		}
		
		else{
		
			if(level.campwarntime){
			
				if(distance(startpos, endpos) < 25) campingtime++;
					else campingtime = 0;
				
				if(campingtime == level.campwarntime)
					show_warning = true;
			}
			
			else continue;
		}
		
		if(show_warning){
		
			self iprintlnbold(&"CAMPING_WARNING_MESSAGE_SELF", self.name);
				
			show_warning = false;
		}
		
		if((campingtime >= level.campobjtime || snipercampingtime >= level.campsniper_objtime)){
		
			self thread MarkCamper();
			return;
		}
	}
	
	campingtime = 0;
	snipercampingtime = 0;
	show_warning = false;
	
}

MarkCamper(){

	level endon("gameover");
	level endon("round_ended");

	self endon("dead");
	self endon("stopcamper");
	self endon("disconnect");


	if(self.iscamper || (isDefined(level.roundended) && level.roundended) || self.sessionstate != "playing") return;

	self.objnum = GetObjective();
	
	if(self.objnum){
	
		self.iscamper = true;
		
		self iprintlnbold(&"CAMPING_MARKED_MESSAGE_SELF", self.name);
		self iprintlnbold(&"CAMPING_TIME_MESSAGE_SELF", level.camptimer);
		
		iprintln(&"CAMPING_MARKED_MESSAGE_ALL", self.name);
		iprintln(&"CAMPING_TIME_MESSAGE_ALL", level.camptimer);
		
		compass_team = "none";
		
		if(self.pers["team"] == "allies") compass_icon = "objective_" + game["allies"];
			else compass_icon = "objective_" + game["axis"];
		
		objective_add(self.objnum, "current", self.origin, compass_icon);
		objective_team(self.objnum, compass_team);
		
		if(level.camptimer >= 1)
			self thread CountCamper();
		
		while(isPlayer(self) && isAlive(self) && self.pers["team"] != "spectator"){
		
			for(i=0;(i<60 && isPlayer(self) && isAlive(self));i++){
			
				if((i <= 29) && self.iscamper) objective_icon(self.objnum, "objpoint_radio");
				else if((i >= 30) && self.iscamper) objective_icon(self.objnum, compass_icon);
				
				if(self.iscamper) objective_position(self.objnum, self.origin);
				
				wait 0.05;
			}
			
			if(isPlayer(self)){
			
				playfxontag(level.effect["fartbomb"], self, "pelvis");
				
				self playLocalSound("fart");
			}
		}
	}
}

CountCamper(){

	self endon("dead");
	self endon("disconnect");
	self endon("spawned");

	wait level.camptimer - 1;

	if(isPlayer(self)){
	
		self notify("stopcamper");
		self.iscamper = false;
		
		wait 1;
	}

	if(isAlive(self)){
	
		self iprintlnbold(&"CAMPING_SURVIVED_MESSAGE_SELF", self.name);
		
		iprintln(&"CAMPING_SURVIVED_MESSAGE_ALL", self.name);
		
		self RemoveCamper();
	}
}

MessageCamperDied(){

	if(self.iscamper == true){
	
		self notify("stopcamper");
		
		self.iscamper = false;
		
		self iprintlnbold(&"CAMPING_DIED_MESSAGE_SELF", self.name);
		iprintln(&"CAMPING_DIED_MESSAGE_ALL", self.name);
		
		self RemoveCamper();
	}
}

WeaponType(weapon, type){

	if(!isDefined(weapon)) return false;

	switch(type){
	
		case "sniper":
		switch(weapon){
		
			case "mosin_nagant_sniper_mp":
			case "springfield_mp":
			case "kar98k_sniper_mp":
			case "enfield_scope_mp": return true;
			default: return false;
		}
	}
	
	return false;
}

RemoveCampers(){

	player = "";
	players = getentarray("player", "classname");

	for(i = 0; i < players.size; i++){
	
		if(isPlayer(players[i]) && isDefined(players[i].objnum))
		
		players[i] RemoveCamper();
	}
}

RemoveCamper(){

	self endon("dead");
	self endon("disconnect");

	if(isDefined(self.objnum)){
	
		DeleteObjective(self.objnum);
		
		self.objnum = undefined;
	}
	
	self thread CheckCamping();
}

GetObjective(){

	if(!isDefined(level.objectives)) CreateObjectivesArray();

	objnum = 0;

	for(i = 15; i >= 4; i--){
	
		if(level.objectives[i] == 0){
		
			level.objectives[i] = 1;
			objnum = i;
			break;
		}
	}
	
	return objnum;
}

DeleteObjective(objnum){


	if(!isDefined(level.objectives)) CreateObjectivesArray();

	if(level.objectives[objnum] == 1){
	
		objective_delete(objnum);
		level.objectives[objnum] = 0;
	}
}

CreateObjectivesArray(){

	if(!isDefined(level.objectives)) level.objectives = [];

	for(i = 0; i <= 15; i++){
	
		if(i < 4) level.objectives[i] = 1;
		else level.objectives[i] = 0;
	}
}



Abschliessend sollten wir das noch in unsere Server.cfg aufnehmen:

Code einblendenCode angehängt. Klicke hier zum Ein-/Ausblenden

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*** Anti Camper Option ***//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Time, before Movewarning to a Player (No Sniper)
// 0 = disable, max = 300, default = 0
set campwarntime "10"

// Time, before Movewarning to a Player (Sniper)
// 0 = disable, max = 600, default = 0
set campsniper_warntime "20"

// Time, before Punishment starts (No Sniper)
// min = warntime + 5, max = 600 (default = warntime + 10)
set campobjtime "10"

// Time, before Punishment starts (Sniper)
// min = warntime + 5, max = 1200, (default = warntime + 10)
set campsniper_objtime "20"

// Time for Length of Punishment
// 0 = never, max = 300, default = 20
set camptimer "15"

// Or you may wish camper option on a particalar map or
// gametype, or even both?...here are some examples... remember not
// to use // if you decide to create one!

// Gametypes
//set no_camper_dm "1"
set no_camper_sd "1"

// Maps
//set no_camper_mtl_hobbiton "1"
set no_camper_gob_rats "1"



So, das wars auch schon, wünsche frohes Campen Augenzwinkern

ToM

EDIT: Hier der Download: KLICK

Okay, wenn ich mir so die Anzahl der Edits ansehe, hätte etwas mehr Schlaf gutgetan Augenzwinkern

EDIT vom Edit vom Edit: Wer's schon gedownloadet hat, bitte nochmal, hab was verpennt reinzumachen, jetzt funzt es optimal.
{LSB} Squall69
Nightwing ich hab mir das Ding nochmal angesehen, und etwas überarbeitet lol.

Hab es jetzt als echten standalone aufgebaut wo du nun auch ohne self Variablen def kannst.

Habs zwar nur kurz angetestet aber ich glaub es tut feini.
Nightwing
Subber Sach Grins 1

Hab grad die Email gelesen, Test erfolgt heut Abend Augenzwinkern

Danke!!

EDIT: Habs grad getestet, saubere Sache!!! Der Thread hier ist editiert. Augenzwinkern
yoda
Für CoD2?
{LSB} Squall69
Ja
yoda
Merci smile
Nice work!!!
Nightwing
Dankschee!

Hab schon wieder was neues im Kopf, ist echt schlimm, die Scripterei Augenzwinkern
Von mir aus könnt CoD 4 sich noch n Jahr Zeit lassen bis zum Release...

ToM
Lufung
Hi Nightwing

weis das es schon ne zeit her ist mit dem Mod aber hättest du den Anti Camper Mod noch??? Bräuchte es für einen COD 4 Server.

Hatte schon den Download link versucht aber funzt nicht mehr. oder vieleicht ein Mod wo die Camper Explodieren wäre echt super.

Danke dir schon mal in vorraus für die mühen

Lufung
Nightwing
Hallo lufung,

Du könntest versuchen, es von CoD2 auf CoD4 zu portieren, hier der Link: standalone Version & modifiziert

ToM