seta cl_weaponpriority "vaporizer vortex fireball mortar machinegun hagar rifle arc electro devastator crylink minelayer shotgun hlac tuba blaster porto seeker hook" "weapon priority list"
seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list (the special value 2 uses the weapon ID list for cycling)"
-seta cl_weaponpriority0 "devastator mortar hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
-seta cl_weaponpriority1 "vaporizer vortex crylink hlac arc electro blaster shockwave" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
-seta cl_weaponpriority2 "vaporizer vortex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact"
-seta cl_weaponpriority3 "vaporizer vortex rifle machinegun shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all"
-seta cl_weaponpriority4 "mortar minelayer hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons"
-seta cl_weaponpriority5 "blaster shockwave hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving"
-seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun"
-seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun"
-seta cl_weaponpriority8 "" "use impulse 208 for prev gun from this list, 218 for best gun, 228 for next gun"
-seta cl_weaponpriority9 "" "use impulse 209 for prev gun from this list, 219 for best gun, 229 for next gun"
+seta cl_weaponpriority0 "devastator mortar hagar seeker fireball" "use weapon_priority_0_prev for prev gun from this list, weapon_priority_0_best for best gun, weapon_priority_0_next for next gun. Default value: explosives"
+seta cl_weaponpriority1 "vaporizer vortex crylink hlac arc electro blaster shockwave" "use weapon_priority_1_prev for prev gun from this list, weapon_priority_1_best for best gun, weapon_priority_1_next for next gun. Default value: energy"
+seta cl_weaponpriority2 "vaporizer vortex rifle" "use weapon_priority_2_prev for prev gun from this list, weapon_priority_2_best for best gun, weapon_priority_2_next for next gun. Default value: hitscan exact"
+seta cl_weaponpriority3 "vaporizer vortex rifle machinegun shotgun" "use weapon_priority_3_prev for prev gun from this list, weapon_priority_3_best for best gun, weapon_priority_3_next for next gun. Default value: hitscan all"
+seta cl_weaponpriority4 "mortar minelayer hlac hagar crylink seeker shotgun" "use weapon_priority_4_prev for prev gun from this list, weapon_priority_4_best for best gun, weapon_priority_4_next for next gun. Default value: spam weapons"
+seta cl_weaponpriority5 "blaster shockwave hook porto" "use weapon_priority_5_prev for prev gun from this list, weapon_priority_5_best for best gun, weapon_priority_5_next for next gun. Default value: weapons for moving"
+seta cl_weaponpriority6 "" "use weapon_priority_6_prev for prev gun from this list, weapon_priority_6_best for best gun, weapon_priority_6_next for next gun"
+seta cl_weaponpriority7 "" "use weapon_priority_7_prev for prev gun from this list, weapon_priority_7_best for best gun, weapon_priority_7_next for next gun"
+seta cl_weaponpriority8 "" "use weapon_priority_8_prev for prev gun from this list, weapon_priority_8_best for best gun, weapon_priority_8_next for next gun"
+seta cl_weaponpriority9 "" "use weapon_priority_9_prev for prev gun from this list, weapon_priority_9_best for best gun, weapon_priority_9_next for next gun"
seta cl_weaponimpulsemode 0 "0: only cycle between currently usable weapons in weapon priority order; 1: cycle between all possible weapons on a key in weapon priority order"
set g_maplist_allow_hidden 0 "allow hidden maps to be, e.g., voted for and in the maplist"
-// bulldozer storage "level4" last updated 16-11-2015 04:16:07
-nextlevel = "level1"
-"e15" 3 "0 0 0"
-"f14" 3 "0 0 0"
-"g13" 3 "0 0 0"
-"k13" 3 "0 0 0"
-"b14" 4 "0 0 0"
-"a14" 4 "0 0 0"
-"a13" 4 "0 0 0"
-"b13" 4 "0 0 0"
-"i13" 3 "0 0 0"
-"m13" 3 "0 0 0"
-"n14" 3 "0 0 0"
-"o15" 3 "0 0 0"
-"h17" 2 "0 0 0"
-"l17" 2 "0 0 0"
-"c12" 2 "0 0 0"
-"c13" 2 "0 0 0"
-"c14" 2 "0 0 0"
-"r14" 2 "0 0 0"
-"r13" 2 "0 0 0"
-"r12" 2 "0 0 0"
-"j15" 1 "0 -1 0"
-"s13" 4 "0 0 0"
-"t13" 4 "0 0 0"
-"t12" 4 "0 0 0"
-"s12" 4 "0 0 0"
-"b12" 4 "0 0 0"
-"a12" 4 "0 0 0"
-"a11" 4 "0 0 0"
-"b11" 4 "0 0 0"
-"c11" 4 "0 0 0"
-"d11" 4 "0 0 0"
-"e11" 4 "0 0 0"
-"f11" 4 "0 0 0"
-"g11" 4 "0 0 0"
-"h11" 4 "0 0 0"
-"i11" 4 "0 0 0"
-"j11" 4 "0 0 0"
-"k11" 4 "0 0 0"
-"l11" 4 "0 0 0"
-"m11" 4 "0 0 0"
-"n11" 4 "0 0 0"
-"o11" 4 "0 0 0"
-"p11" 4 "0 0 0"
-"q11" 4 "0 0 0"
-"r11" 4 "0 0 0"
-"s11" 4 "0 0 0"
-"t11" 4 "0 0 0"
-"t6" 6 "0 0 0"
-"s10" 4 "0 0 0"
-"r10" 4 "0 0 0"
-"q10" 4 "0 0 0"
-"b10" 6 "0 0 0"
-"o10" 4 "0 0 0"
-"c10" 6 "0 0 0"
-"d10" 6 "0 0 0"
-"e6" 4 "0 0 0"
-"b9" 6 "0 0 0"
-"b8" 6 "0 0 0"
-"c7" 4 "0 0 0"
-"b7" 6 "0 0 0"
-"b6" 6 "0 0 0"
-"c6" 6 "0 0 0"
-"d6" 6 "0 0 0"
-"f10" 6 "0 0 0"
-"g10" 6 "0 0 0"
-"h10" 6 "0 0 0"
-"a10" 4 "0 0 0"
-"a9" 4 "0 0 0"
-"h9" 4 "0 0 0"
-"c9" 4 "0 0 0"
-"d9" 4 "0 0 0"
-"h8" 4 "0 0 0"
-"h7" 4 "0 0 0"
-"i10" 6 "0 0 0"
-"i9" 6 "0 0 0"
-"j7" 4 "0 0 0"
-"j6" 4 "0 0 0"
-"j10" 4 "0 0 0"
-"i8" 6 "0 0 0"
-"m9" 4 "0 0 0"
-"i7" 6 "0 0 0"
-"o9" 4 "0 0 0"
-"i6" 6 "0 0 0"
-"q9" 4 "0 0 0"
-"r9" 4 "0 0 0"
-"s9" 4 "0 0 0"
-"h6" 6 "0 0 0"
-"g6" 6 "0 0 0"
-"s8" 4 "0 0 0"
-"r8" 4 "0 0 0"
-"q8" 4 "0 0 0"
-"f6" 6 "0 0 0"
-"o8" 4 "0 0 0"
-"f7" 6 "0 0 0"
-"m8" 4 "0 0 0"
-"f8" 6 "0 0 0"
-"f9" 6 "0 0 0"
-"k10" 6 "0 0 0"
-"e10" 4 "0 0 0"
-"d7" 4 "0 0 0"
-"e9" 4 "0 0 0"
-"e8" 4 "0 0 0"
-"e7" 4 "0 0 0"
-"l10" 6 "0 0 0"
-"c8" 4 "0 0 0"
-"m10" 6 "0 0 0"
-"a8" 4 "0 0 0"
-"a7" 4 "0 0 0"
-"g7" 4 "0 0 0"
-"g8" 4 "0 0 0"
-"g9" 4 "0 0 0"
-"n10" 6 "0 0 0"
-"n9" 6 "0 0 0"
-"n8" 6 "0 0 0"
-"d8" 4 "0 0 0"
-"n7" 6 "0 0 0"
-"n6" 6 "0 0 0"
-"m6" 6 "0 0 0"
-"l6" 6 "0 0 0"
-"m7" 4 "0 0 0"
-"k6" 6 "0 0 0"
-"o7" 4 "0 0 0"
-"k7" 6 "0 0 0"
-"q7" 4 "0 0 0"
-"r7" 4 "0 0 0"
-"s7" 4 "0 0 0"
-"k8" 6 "0 0 0"
-"k9" 6 "0 0 0"
-"s6" 4 "0 0 0"
-"p9" 6 "0 0 0"
-"p8" 6 "0 0 0"
-"p7" 6 "0 0 0"
-"o6" 4 "0 0 0"
-"p6" 6 "0 0 0"
-"q6" 6 "0 0 0"
-"r6" 6 "0 0 0"
-"p10" 6 "0 0 0"
-"j9" 4 "0 0 0"
-"j8" 4 "0 0 0"
-"t10" 6 "0 0 0"
-"t9" 6 "0 0 0"
-"t8" 6 "0 0 0"
-"l7" 4 "0 0 0"
-"l8" 4 "0 0 0"
-"l9" 4 "0 0 0"
-"t7" 4 "0 0 0"
-"a6" 4 "0 0 0"
-"a5" 4 "0 0 0"
-"b5" 4 "0 0 0"
-"c5" 4 "0 0 0"
-"d5" 4 "0 0 0"
-"e5" 4 "0 0 0"
-"f5" 4 "0 0 0"
-"g5" 4 "0 0 0"
-"h5" 4 "0 0 0"
-"i5" 4 "0 0 0"
-"j5" 4 "0 0 0"
-"k5" 4 "0 0 0"
-"l5" 4 "0 0 0"
-"m5" 4 "0 0 0"
-"n5" 4 "0 0 0"
-"o5" 4 "0 0 0"
-"p5" 4 "0 0 0"
-"q5" 4 "0 0 0"
-"r5" 4 "0 0 0"
-"s5" 4 "0 0 0"
-"t5" 4 "0 0 0"
-"t4" 4 "0 0 0"
-"s4" 4 "0 0 0"
-"r4" 4 "0 0 0"
-"q4" 4 "0 0 0"
-"p4" 4 "0 0 0"
-"o4" 4 "0 0 0"
-"n4" 4 "0 0 0"
-"m4" 4 "0 0 0"
-"l4" 4 "0 0 0"
-"k4" 4 "0 0 0"
-"j4" 4 "0 0 0"
-"i4" 4 "0 0 0"
-"h4" 4 "0 0 0"
-"g4" 4 "0 0 0"
-"f4" 4 "0 0 0"
-"e4" 4 "0 0 0"
-"d4" 4 "0 0 0"
-"c4" 4 "0 0 0"
-"b4" 4 "0 0 0"
-"a4" 4 "0 0 0"
-"a3" 4 "0 0 0"
-"b3" 4 "0 0 0"
-"c3" 4 "0 0 0"
-"d3" 4 "0 0 0"
-"e3" 4 "0 0 0"
-"f3" 4 "0 0 0"
-"g3" 4 "0 0 0"
-"h3" 4 "0 0 0"
-"i3" 4 "0 0 0"
-"j3" 4 "0 0 0"
-"k3" 4 "0 0 0"
-"l3" 4 "0 0 0"
-"m3" 4 "0 0 0"
-"n3" 4 "0 0 0"
-"o3" 4 "0 0 0"
-"p3" 4 "0 0 0"
-"q3" 4 "0 0 0"
-"r3" 4 "0 0 0"
-"s3" 4 "0 0 0"
-"t3" 4 "0 0 0"
-"t2" 4 "0 0 0"
-"s2" 4 "0 0 0"
-"r2" 4 "0 0 0"
-"q2" 4 "0 0 0"
-"p2" 4 "0 0 0"
-"o2" 4 "0 0 0"
-"n2" 4 "0 0 0"
-"m2" 4 "0 0 0"
-"l2" 4 "0 0 0"
-"k2" 4 "0 0 0"
-"j2" 4 "0 0 0"
-"i2" 4 "0 0 0"
-"h2" 4 "0 0 0"
-"g2" 4 "0 0 0"
-"f2" 4 "0 0 0"
-"e2" 4 "0 0 0"
-"d2" 4 "0 0 0"
-"c2" 4 "0 0 0"
-"b2" 4 "0 0 0"
-"a2" 4 "0 0 0"
-"a1" 4 "0 0 0"
-"b1" 4 "0 0 0"
-"c1" 4 "0 0 0"
-"d1" 4 "0 0 0"
-"e1" 4 "0 0 0"
-"f1" 4 "0 0 0"
-"g1" 4 "0 0 0"
-"h1" 4 "0 0 0"
-"i1" 4 "0 0 0"
-"j1" 4 "0 0 0"
-"k1" 4 "0 0 0"
-"l1" 4 "0 0 0"
-"m1" 4 "0 0 0"
-"n1" 4 "0 0 0"
-"o1" 4 "0 0 0"
-"p1" 4 "0 0 0"
-"q1" 4 "0 0 0"
-"r1" 4 "0 0 0"
-"s1" 4 "0 0 0"
-"t1" 4 "0 0 0"
-"t14" 4 "0 0 0"
-"s14" 4 "0 0 0"
-"b15" 4 "0 0 0"
-"a15" 4 "0 0 0"
-"a16" 4 "0 0 0"
-"b16" 4 "0 0 0"
-"s16" 4 "0 0 0"
-"t16" 4 "0 0 0"
-"t15" 4 "0 0 0"
-"s15" 4 "0 0 0"
-"t17" 4 "0 0 0"
-"s17" 4 "0 0 0"
-"b17" 4 "0 0 0"
-"a17" 4 "0 0 0"
-"a18" 4 "0 0 0"
-"b18" 4 "0 0 0"
-"s18" 4 "0 0 0"
-"t18" 4 "0 0 0"
-"t19" 4 "0 0 0"
-"s19" 4 "0 0 0"
-"r19" 4 "0 0 0"
-"q19" 4 "0 0 0"
-"p19" 4 "0 0 0"
-"o19" 4 "0 0 0"
-"n19" 4 "0 0 0"
-"m19" 4 "0 0 0"
-"l19" 4 "0 0 0"
-"k19" 4 "0 0 0"
-"j19" 4 "0 0 0"
-"i19" 4 "0 0 0"
-"h19" 4 "0 0 0"
-"g19" 4 "0 0 0"
-"f19" 4 "0 0 0"
-"e19" 4 "0 0 0"
-"d19" 4 "0 0 0"
-"c19" 4 "0 0 0"
-"b19" 4 "0 0 0"
-"a19" 4 "0 0 0"
-"a20" 4 "0 0 0"
-"b20" 4 "0 0 0"
-"c20" 4 "0 0 0"
-"d20" 4 "0 0 0"
-"e20" 4 "0 0 0"
-"f20" 4 "0 0 0"
-"g20" 4 "0 0 0"
-"h20" 4 "0 0 0"
-"i20" 4 "0 0 0"
-"j20" 4 "0 0 0"
-"k20" 4 "0 0 0"
-"l20" 4 "0 0 0"
-"m20" 4 "0 0 0"
-"n20" 4 "0 0 0"
-"o20" 4 "0 0 0"
-"p20" 4 "0 0 0"
-"q20" 4 "0 0 0"
-"r20" 4 "0 0 0"
-"s20" 4 "0 0 0"
-"t20" 4 "0 0 0"
+// bulldozer storage "level6" last updated 06-12-2015 16:11:35
+nextlevel = "level7"
+"g13" 5 "0 -1 0"
+"f13" 5 "0 -1 0"
+"f12" 5 "0 -1 0"
+"f11" 5 "0 -1 0"
+"f10" 5 "0 -1 0"
+"g10" 5 "0 -1 0"
+"i9" 5 "0 -1 0"
+"g9" 5 "0 -1 0"
+"h9" 5 "0 -1 0"
+"j9" 5 "0 -1 0"
+"k9" 5 "0 -1 0"
+"l9" 5 "0 -1 0"
+"m9" 5 "0 -1 0"
+"n9" 5 "0 -1 0"
+"n10" 5 "0 -1 0"
+"o12" 5 "0 -1 0"
+"n11" 5 "0 -1 0"
+"o11" 5 "0 -1 0"
+"n14" 5 "0 -1 0"
+"o13" 5 "0 -1 0"
+"o14" 5 "0 -1 0"
+"m14" 5 "0 -1 0"
+"l15" 5 "0 -1 0"
+"m15" 5 "0 -1 0"
+"g14" 5 "0 -1 0"
+"g15" 5 "0 -1 0"
+"h15" 5 "0 -1 0"
+"i15" 5 "0 -1 0"
+"j15" 5 "0 -1 0"
+"k15" 5 "0 -1 0"
+"i13" 5 "0 -1 0"
+"j13" 5 "0 -1 0"
+"k13" 5 "0 -1 0"
+"j10" 5 "0 -1 0"
+"j11" 5 "0 -1 0"
+"h10" 2 "0 -1 0"
+"i10" 2 "0 -1 0"
+"h11" 2 "0 -1 0"
+"i11" 2 "0 -1 0"
+"g12" 1 "0 -1 0"
+"h13" 3 "0 -1 0"
+"j12" 3 "0 -1 0"
+"l11" 3 "0 -1 0"
+"m12" 3 "0 -1 0"
+"b2" 4 "0 -1 0"
+"b3" 4 "0 -1 0"
+"c3" 4 "0 -1 0"
+"c2" 4 "0 -1 0"
+"b19" 4 "0 -1 0"
+"b18" 4 "0 -1 0"
+"c18" 4 "0 -1 0"
+"c19" 4 "0 -1 0"
+"r19" 4 "0 -1 0"
+"r18" 4 "0 -1 0"
+"s18" 4 "0 -1 0"
+"s19" 4 "0 -1 0"
+"r2" 4 "0 -1 0"
+"r3" 4 "0 -1 0"
+"s3" 4 "0 -1 0"
+"s2" 4 "0 -1 0"
+"f5" 6 "0 -1 0"
+"e5" 6 "0 -1 0"
+"d5" 6 "0 -1 0"
+"c5" 6 "0 -1 0"
+"b5" 6 "0 -1 0"
+"a5" 6 "0 -1 0"
+"a4" 6 "0 -1 0"
+"b4" 6 "0 -1 0"
+"c4" 6 "0 -1 0"
+"d4" 6 "0 -1 0"
+"e4" 6 "0 -1 0"
+"f4" 6 "0 -1 0"
+"g4" 6 "0 -1 0"
+"h4" 6 "0 -1 0"
+"i4" 6 "0 -1 0"
+"j4" 6 "0 -1 0"
+"k4" 6 "0 -1 0"
+"l4" 6 "0 -1 0"
+"m4" 6 "0 -1 0"
+"n4" 6 "0 -1 0"
+"o4" 6 "0 -1 0"
+"p4" 6 "0 -1 0"
+"q4" 6 "0 -1 0"
+"r4" 6 "0 -1 0"
+"s4" 6 "0 -1 0"
+"t4" 6 "0 -1 0"
+"t3" 6 "0 -1 0"
+"t2" 6 "0 -1 0"
+"t1" 6 "0 -1 0"
+"s1" 6 "0 -1 0"
+"r1" 6 "0 -1 0"
+"q1" 6 "0 -1 0"
+"p1" 6 "0 -1 0"
+"o1" 6 "0 -1 0"
+"n1" 6 "0 -1 0"
+"m1" 6 "0 -1 0"
+"l1" 6 "0 -1 0"
+"k1" 6 "0 -1 0"
+"j1" 6 "0 -1 0"
+"i1" 6 "0 -1 0"
+"h1" 6 "0 -1 0"
+"g1" 6 "0 -1 0"
+"f1" 6 "0 -1 0"
+"e1" 6 "0 -1 0"
+"d1" 6 "0 -1 0"
+"c1" 6 "0 -1 0"
+"b1" 6 "0 -1 0"
+"a1" 6 "0 -1 0"
+"a2" 6 "0 -1 0"
+"a3" 6 "0 -1 0"
+"d2" 6 "0 -1 0"
+"e2" 6 "0 -1 0"
+"f2" 6 "0 -1 0"
+"g2" 6 "0 -1 0"
+"h2" 6 "0 -1 0"
+"i2" 6 "0 -1 0"
+"j2" 6 "0 -1 0"
+"k2" 6 "0 -1 0"
+"l2" 6 "0 -1 0"
+"m2" 6 "0 -1 0"
+"n2" 6 "0 -1 0"
+"o2" 6 "0 -1 0"
+"p2" 6 "0 -1 0"
+"q2" 6 "0 -1 0"
+"q3" 6 "0 -1 0"
+"p3" 6 "0 -1 0"
+"o3" 6 "0 -1 0"
+"n3" 6 "0 -1 0"
+"m3" 6 "0 -1 0"
+"l3" 6 "0 -1 0"
+"k3" 6 "0 -1 0"
+"j3" 6 "0 -1 0"
+"i3" 6 "0 -1 0"
+"h3" 6 "0 -1 0"
+"g3" 6 "0 -1 0"
+"f3" 6 "0 -1 0"
+"e3" 6 "0 -1 0"
+"d3" 6 "0 -1 0"
+"t5" 6 "0 -1 0"
+"s5" 6 "0 -1 0"
+"r5" 6 "0 -1 0"
+"q5" 6 "0 -1 0"
+"p5" 6 "0 -1 0"
+"o5" 6 "0 -1 0"
+"n5" 6 "0 -1 0"
+"m5" 6 "0 -1 0"
+"l5" 6 "0 -1 0"
+"k5" 6 "0 -1 0"
+"j5" 6 "0 -1 0"
+"i5" 6 "0 -1 0"
+"h5" 6 "0 -1 0"
+"g5" 6 "0 -1 0"
+"g6" 6 "0 -1 0"
+"f6" 6 "0 -1 0"
+"e6" 6 "0 -1 0"
+"d6" 6 "0 -1 0"
+"c6" 6 "0 -1 0"
+"b6" 6 "0 -1 0"
+"a6" 6 "0 -1 0"
+"a7" 6 "0 -1 0"
+"b7" 6 "0 -1 0"
+"c7" 6 "0 -1 0"
+"d7" 6 "0 -1 0"
+"e7" 6 "0 -1 0"
+"f7" 6 "0 -1 0"
+"g7" 6 "0 -1 0"
+"h7" 6 "0 -1 0"
+"i7" 6 "0 -1 0"
+"j7" 6 "0 -1 0"
+"k7" 6 "0 -1 0"
+"l7" 6 "0 -1 0"
+"m7" 6 "0 -1 0"
+"n7" 6 "0 -1 0"
+"o7" 6 "0 -1 0"
+"p7" 6 "0 -1 0"
+"q7" 6 "0 -1 0"
+"r7" 6 "0 -1 0"
+"s7" 6 "0 -1 0"
+"t7" 6 "0 -1 0"
+"t6" 6 "0 -1 0"
+"s6" 6 "0 -1 0"
+"r6" 6 "0 -1 0"
+"q6" 6 "0 -1 0"
+"p6" 6 "0 -1 0"
+"o6" 6 "0 -1 0"
+"n6" 6 "0 -1 0"
+"m6" 6 "0 -1 0"
+"l6" 6 "0 -1 0"
+"k6" 6 "0 -1 0"
+"j6" 6 "0 -1 0"
+"i6" 6 "0 -1 0"
+"h6" 6 "0 -1 0"
+"t8" 6 "0 -1 0"
+"s8" 6 "0 -1 0"
+"r8" 6 "0 -1 0"
+"q8" 6 "0 -1 0"
+"p8" 6 "0 -1 0"
+"o8" 6 "0 -1 0"
+"n8" 6 "0 -1 0"
+"m8" 6 "0 -1 0"
+"l8" 6 "0 -1 0"
+"k8" 6 "0 -1 0"
+"j8" 6 "0 -1 0"
+"i8" 6 "0 -1 0"
+"h8" 6 "0 -1 0"
+"g8" 6 "0 -1 0"
+"f8" 6 "0 -1 0"
+"e8" 6 "0 -1 0"
+"d8" 6 "0 -1 0"
+"c8" 6 "0 -1 0"
+"b8" 6 "0 -1 0"
+"a8" 6 "0 -1 0"
+"a9" 6 "0 -1 0"
+"b9" 6 "0 -1 0"
+"c9" 6 "0 -1 0"
+"d9" 6 "0 -1 0"
+"e9" 6 "0 -1 0"
+"f9" 6 "0 -1 0"
+"e10" 6 "0 -1 0"
+"d10" 6 "0 -1 0"
+"c10" 6 "0 -1 0"
+"b10" 6 "0 -1 0"
+"a10" 6 "0 -1 0"
+"a11" 6 "0 -1 0"
+"b11" 6 "0 -1 0"
+"c11" 6 "0 -1 0"
+"d11" 6 "0 -1 0"
+"e11" 6 "0 -1 0"
+"e12" 6 "0 -1 0"
+"d12" 6 "0 -1 0"
+"c12" 6 "0 -1 0"
+"b12" 6 "0 -1 0"
+"a12" 6 "0 -1 0"
+"a13" 6 "0 -1 0"
+"b13" 6 "0 -1 0"
+"c13" 6 "0 -1 0"
+"d13" 6 "0 -1 0"
+"e13" 6 "0 -1 0"
+"e14" 6 "0 -1 0"
+"d14" 6 "0 -1 0"
+"c14" 6 "0 -1 0"
+"b14" 6 "0 -1 0"
+"a14" 6 "0 -1 0"
+"a15" 6 "0 -1 0"
+"b15" 6 "0 -1 0"
+"c15" 6 "0 -1 0"
+"d15" 6 "0 -1 0"
+"e15" 6 "0 -1 0"
+"f15" 6 "0 -1 0"
+"f14" 6 "0 -1 0"
+"f16" 6 "0 -1 0"
+"e16" 6 "0 -1 0"
+"d16" 6 "0 -1 0"
+"c16" 6 "0 -1 0"
+"b16" 6 "0 -1 0"
+"a16" 6 "0 -1 0"
+"a17" 6 "0 -1 0"
+"b17" 6 "0 -1 0"
+"c17" 6 "0 -1 0"
+"d17" 6 "0 -1 0"
+"e17" 6 "0 -1 0"
+"f17" 6 "0 -1 0"
+"g17" 6 "0 -1 0"
+"h17" 6 "0 -1 0"
+"i17" 6 "0 -1 0"
+"j17" 6 "0 -1 0"
+"k17" 6 "0 -1 0"
+"l17" 6 "0 -1 0"
+"m17" 6 "0 -1 0"
+"n17" 6 "0 -1 0"
+"o17" 6 "0 -1 0"
+"p17" 6 "0 -1 0"
+"q17" 6 "0 -1 0"
+"r17" 6 "0 -1 0"
+"s17" 6 "0 -1 0"
+"t17" 6 "0 -1 0"
+"t16" 6 "0 -1 0"
+"s16" 6 "0 -1 0"
+"r16" 6 "0 -1 0"
+"q16" 6 "0 -1 0"
+"p16" 6 "0 -1 0"
+"o16" 6 "0 -1 0"
+"n16" 6 "0 -1 0"
+"m16" 6 "0 -1 0"
+"l16" 6 "0 -1 0"
+"k16" 6 "0 -1 0"
+"j16" 6 "0 -1 0"
+"i16" 6 "0 -1 0"
+"h16" 6 "0 -1 0"
+"g16" 6 "0 -1 0"
+"n15" 6 "0 -1 0"
+"o15" 6 "0 -1 0"
+"p15" 6 "0 -1 0"
+"q15" 6 "0 -1 0"
+"r15" 6 "0 -1 0"
+"s15" 6 "0 -1 0"
+"t15" 6 "0 -1 0"
+"t14" 6 "0 -1 0"
+"s14" 6 "0 -1 0"
+"r14" 6 "0 -1 0"
+"q14" 6 "0 -1 0"
+"p14" 6 "0 -1 0"
+"p13" 6 "0 -1 0"
+"q13" 6 "0 -1 0"
+"r13" 6 "0 -1 0"
+"s13" 6 "0 -1 0"
+"t13" 6 "0 -1 0"
+"t12" 6 "0 -1 0"
+"s12" 6 "0 -1 0"
+"r12" 6 "0 -1 0"
+"q12" 6 "0 -1 0"
+"p12" 6 "0 -1 0"
+"p11" 6 "0 -1 0"
+"q11" 6 "0 -1 0"
+"r11" 6 "0 -1 0"
+"s11" 6 "0 -1 0"
+"t11" 6 "0 -1 0"
+"t10" 6 "0 -1 0"
+"s10" 6 "0 -1 0"
+"r10" 6 "0 -1 0"
+"q10" 6 "0 -1 0"
+"p10" 6 "0 -1 0"
+"o10" 6 "0 -1 0"
+"o9" 6 "0 -1 0"
+"p9" 6 "0 -1 0"
+"q9" 6 "0 -1 0"
+"r9" 6 "0 -1 0"
+"s9" 6 "0 -1 0"
+"t9" 6 "0 -1 0"
+"t18" 6 "0 -1 0"
+"t19" 6 "0 -1 0"
+"t20" 6 "0 -1 0"
+"s20" 6 "0 -1 0"
+"r20" 6 "0 -1 0"
+"q20" 6 "0 -1 0"
+"p20" 6 "0 -1 0"
+"o20" 6 "0 -1 0"
+"n20" 6 "0 -1 0"
+"m20" 6 "0 -1 0"
+"l20" 6 "0 -1 0"
+"k20" 6 "0 -1 0"
+"j20" 6 "0 -1 0"
+"i20" 6 "0 -1 0"
+"h20" 6 "0 -1 0"
+"g20" 6 "0 -1 0"
+"f20" 6 "0 -1 0"
+"e20" 6 "0 -1 0"
+"d20" 6 "0 -1 0"
+"c20" 6 "0 -1 0"
+"b20" 6 "0 -1 0"
+"a20" 6 "0 -1 0"
+"a19" 6 "0 -1 0"
+"a18" 6 "0 -1 0"
+"d19" 6 "0 -1 0"
+"e19" 6 "0 -1 0"
+"f19" 6 "0 -1 0"
+"g19" 6 "0 -1 0"
+"h19" 6 "0 -1 0"
+"i19" 6 "0 -1 0"
+"j19" 6 "0 -1 0"
+"k19" 6 "0 -1 0"
+"l19" 6 "0 -1 0"
+"m19" 6 "0 -1 0"
+"n19" 6 "0 -1 0"
+"o19" 6 "0 -1 0"
+"p19" 6 "0 -1 0"
+"q19" 6 "0 -1 0"
+"q18" 6 "0 -1 0"
+"p18" 6 "0 -1 0"
+"o18" 6 "0 -1 0"
+"n18" 6 "0 -1 0"
+"m18" 6 "0 -1 0"
+"l18" 6 "0 -1 0"
+"k18" 6 "0 -1 0"
+"j18" 6 "0 -1 0"
+"i18" 6 "0 -1 0"
+"h18" 6 "0 -1 0"
+"g18" 6 "0 -1 0"
+"f18" 6 "0 -1 0"
+"e18" 6 "0 -1 0"
+"d18" 6 "0 -1 0"
--- /dev/null
+// bulldozer storage "level7" last updated 06-12-2015 16:19:03
+nextlevel = "level8"
+"g10" 5 "0 -1 0"
+"g9" 5 "0 -1 0"
+"g8" 5 "0 -1 0"
+"g11" 5 "0 -1 0"
+"g12" 5 "0 -1 0"
+"h8" 5 "0 -1 0"
+"i8" 5 "0 -1 0"
+"j8" 5 "0 -1 0"
+"l8" 5 "0 -1 0"
+"k8" 5 "0 -1 0"
+"m8" 5 "0 -1 0"
+"n8" 5 "0 -1 0"
+"n9" 5 "0 -1 0"
+"n10" 5 "0 -1 0"
+"n11" 5 "0 -1 0"
+"n12" 5 "0 -1 0"
+"m12" 5 "0 -1 0"
+"m13" 5 "0 -1 0"
+"m14" 5 "0 -1 0"
+"h12" 5 "0 -1 0"
+"h13" 5 "0 -1 0"
+"h14" 5 "0 -1 0"
+"h15" 5 "0 -1 0"
+"i15" 5 "0 -1 0"
+"j15" 5 "0 -1 0"
+"k15" 5 "0 -1 0"
+"k14" 5 "0 -1 0"
+"l14" 5 "0 -1 0"
+"k12" 5 "0 -1 0"
+"k11" 5 "0 -1 0"
+"i12" 5 "0 -1 0"
+"i11" 5 "0 -1 0"
+"l10" 5 "0 -1 0"
+"j14" 1 "0 -1 0"
+"j13" 3 "0 -1 0"
+"i10" 3 "0 -1 0"
+"l9" 3 "0 -1 0"
+"h11" 2 "0 -1 0"
+"h10" 2 "0 -1 0"
+"h9" 2 "0 -1 0"
+"a19" 6 "0 -1 0"
+"b20" 6 "0 -1 0"
+"b18" 6 "0 -1 0"
+"a17" 6 "0 -1 0"
+"b16" 6 "0 -1 0"
+"a15" 6 "0 -1 0"
+"b14" 6 "0 -1 0"
+"a13" 6 "0 -1 0"
+"b12" 6 "0 -1 0"
+"a10" 11 "0 -1 0"
+"b10" 6 "0 -1 0"
+"a7" 6 "0 -1 0"
+"a9" 6 "0 -1 0"
+"b8" 6 "0 -1 0"
+"b6" 6 "0 -1 0"
+"a5" 6 "0 -1 0"
+"b4" 6 "0 -1 0"
+"a3" 6 "0 -1 0"
+"b2" 6 "0 -1 0"
+"a1" 6 "0 -1 0"
+"c1" 6 "0 -1 0"
+"d2" 6 "0 -1 0"
+"e1" 6 "0 -1 0"
+"c3" 6 "0 -1 0"
+"c5" 6 "0 -1 0"
+"c7" 6 "0 -1 0"
+"c9" 6 "0 -1 0"
+"c11" 6 "0 -1 0"
+"c13" 6 "0 -1 0"
+"c15" 6 "0 -1 0"
+"c17" 6 "0 -1 0"
+"c19" 6 "0 -1 0"
+"d20" 6 "0 -1 0"
+"d18" 6 "0 -1 0"
+"d16" 6 "0 -1 0"
+"d14" 6 "0 -1 0"
+"d12" 6 "0 -1 0"
+"d10" 6 "0 -1 0"
+"d8" 6 "0 -1 0"
+"d6" 6 "0 -1 0"
+"d4" 6 "0 -1 0"
+"e3" 6 "0 -1 0"
+"e9" 6 "0 -1 0"
+"e5" 6 "0 -1 0"
+"e7" 6 "0 -1 0"
+"e11" 6 "0 -1 0"
+"e13" 6 "0 -1 0"
+"e15" 6 "0 -1 0"
+"e17" 6 "0 -1 0"
+"e19" 6 "0 -1 0"
+"a20" 11 "0 -1 0"
+"b19" 11 "0 -1 0"
+"a18" 11 "0 -1 0"
+"a16" 11 "0 -1 0"
+"a14" 11 "0 -1 0"
+"a12" 11 "0 -1 0"
+"a8" 11 "0 -1 0"
+"a6" 11 "0 -1 0"
+"a4" 11 "0 -1 0"
+"a2" 11 "0 -1 0"
+"b1" 11 "0 -1 0"
+"b3" 11 "0 -1 0"
+"b5" 11 "0 -1 0"
+"b7" 11 "0 -1 0"
+"b9" 11 "0 -1 0"
+"b11" 11 "0 -1 0"
+"b13" 11 "0 -1 0"
+"b15" 11 "0 -1 0"
+"b17" 11 "0 -1 0"
+"c20" 11 "0 -1 0"
+"c18" 11 "0 -1 0"
+"c16" 11 "0 -1 0"
+"c14" 11 "0 -1 0"
+"c12" 11 "0 -1 0"
+"c10" 11 "0 -1 0"
+"c8" 11 "0 -1 0"
+"c6" 11 "0 -1 0"
+"c4" 11 "0 -1 0"
+"c2" 11 "0 -1 0"
+"d1" 11 "0 -1 0"
+"d3" 11 "0 -1 0"
+"d5" 11 "0 -1 0"
+"d7" 11 "0 -1 0"
+"d9" 11 "0 -1 0"
+"d11" 11 "0 -1 0"
+"d13" 11 "0 -1 0"
+"d15" 11 "0 -1 0"
+"d17" 11 "0 -1 0"
+"d19" 11 "0 -1 0"
+"e20" 11 "0 -1 0"
+"e18" 11 "0 -1 0"
+"e16" 11 "0 -1 0"
+"e14" 11 "0 -1 0"
+"e12" 11 "0 -1 0"
+"e10" 11 "0 -1 0"
+"e8" 11 "0 -1 0"
+"e6" 11 "0 -1 0"
+"e4" 11 "0 -1 0"
+"e2" 11 "0 -1 0"
+"a11" 6 "0 -1 0"
+"p1" 6 "0 -1 0"
+"p3" 6 "0 -1 0"
+"p5" 6 "0 -1 0"
+"p7" 6 "0 -1 0"
+"p9" 6 "0 -1 0"
+"p15" 6 "0 -1 0"
+"p11" 6 "0 -1 0"
+"p13" 6 "0 -1 0"
+"q20" 6 "0 -1 0"
+"p17" 6 "0 -1 0"
+"p19" 6 "0 -1 0"
+"q18" 6 "0 -1 0"
+"q16" 6 "0 -1 0"
+"q14" 6 "0 -1 0"
+"q12" 6 "0 -1 0"
+"q10" 6 "0 -1 0"
+"q8" 6 "0 -1 0"
+"q6" 6 "0 -1 0"
+"q4" 6 "0 -1 0"
+"q2" 6 "0 -1 0"
+"r1" 6 "0 -1 0"
+"r3" 6 "0 -1 0"
+"r5" 6 "0 -1 0"
+"r7" 6 "0 -1 0"
+"r9" 6 "0 -1 0"
+"r11" 6 "0 -1 0"
+"r13" 6 "0 -1 0"
+"r15" 6 "0 -1 0"
+"r17" 6 "0 -1 0"
+"r19" 6 "0 -1 0"
+"s20" 6 "0 -1 0"
+"s18" 6 "0 -1 0"
+"s16" 6 "0 -1 0"
+"s14" 6 "0 -1 0"
+"s12" 6 "0 -1 0"
+"s10" 6 "0 -1 0"
+"s8" 6 "0 -1 0"
+"s6" 6 "0 -1 0"
+"s4" 6 "0 -1 0"
+"s2" 6 "0 -1 0"
+"t1" 6 "0 -1 0"
+"t3" 6 "0 -1 0"
+"t5" 6 "0 -1 0"
+"t7" 6 "0 -1 0"
+"t9" 6 "0 -1 0"
+"t11" 6 "0 -1 0"
+"t13" 6 "0 -1 0"
+"t14" 11 "0 -1 0"
+"t17" 6 "0 -1 0"
+"t19" 6 "0 -1 0"
+"p20" 11 "0 -1 0"
+"p18" 11 "0 -1 0"
+"p16" 11 "0 -1 0"
+"p14" 11 "0 -1 0"
+"p12" 11 "0 -1 0"
+"p10" 11 "0 -1 0"
+"p8" 11 "0 -1 0"
+"p6" 11 "0 -1 0"
+"p4" 11 "0 -1 0"
+"p2" 11 "0 -1 0"
+"q1" 11 "0 -1 0"
+"q3" 11 "0 -1 0"
+"q5" 11 "0 -1 0"
+"q7" 11 "0 -1 0"
+"q9" 11 "0 -1 0"
+"q11" 11 "0 -1 0"
+"q13" 11 "0 -1 0"
+"q15" 11 "0 -1 0"
+"q17" 11 "0 -1 0"
+"q19" 11 "0 -1 0"
+"r20" 11 "0 -1 0"
+"r18" 11 "0 -1 0"
+"r16" 11 "0 -1 0"
+"r14" 11 "0 -1 0"
+"r12" 11 "0 -1 0"
+"r10" 11 "0 -1 0"
+"r8" 11 "0 -1 0"
+"r6" 11 "0 -1 0"
+"r4" 11 "0 -1 0"
+"r2" 11 "0 -1 0"
+"s1" 11 "0 -1 0"
+"s3" 11 "0 -1 0"
+"s5" 11 "0 -1 0"
+"s7" 11 "0 -1 0"
+"s9" 11 "0 -1 0"
+"s11" 11 "0 -1 0"
+"s13" 11 "0 -1 0"
+"s15" 11 "0 -1 0"
+"s17" 11 "0 -1 0"
+"s19" 11 "0 -1 0"
+"t20" 11 "0 -1 0"
+"t18" 11 "0 -1 0"
+"t16" 11 "0 -1 0"
+"t10" 11 "0 -1 0"
+"t12" 11 "0 -1 0"
+"t8" 11 "0 -1 0"
+"t6" 11 "0 -1 0"
+"t4" 11 "0 -1 0"
+"t2" 11 "0 -1 0"
+"t15" 6 "0 -1 0"
+"h18" 4 "0 -1 0"
+"g18" 4 "0 -1 0"
+"f18" 4 "0 -1 0"
+"f17" 4 "0 -1 0"
+"g17" 4 "0 -1 0"
+"h17" 4 "0 -1 0"
+"i17" 4 "0 -1 0"
+"j17" 4 "0 -1 0"
+"k17" 4 "0 -1 0"
+"l17" 4 "0 -1 0"
+"m17" 4 "0 -1 0"
+"n17" 4 "0 -1 0"
+"o17" 4 "0 -1 0"
+"o16" 4 "0 -1 0"
+"n16" 4 "0 -1 0"
+"m16" 4 "0 -1 0"
+"l16" 4 "0 -1 0"
+"k16" 4 "0 -1 0"
+"j16" 4 "0 -1 0"
+"i16" 4 "0 -1 0"
+"h16" 4 "0 -1 0"
+"g16" 4 "0 -1 0"
+"f16" 4 "0 -1 0"
+"f15" 4 "0 -1 0"
+"g15" 4 "0 -1 0"
+"g14" 4 "0 -1 0"
+"f14" 4 "0 -1 0"
+"f13" 4 "0 -1 0"
+"g13" 4 "0 -1 0"
+"f12" 4 "0 -1 0"
+"f11" 4 "0 -1 0"
+"f10" 4 "0 -1 0"
+"f9" 4 "0 -1 0"
+"f8" 4 "0 -1 0"
+"f7" 4 "0 -1 0"
+"g7" 4 "0 -1 0"
+"h7" 4 "0 -1 0"
+"i7" 4 "0 -1 0"
+"j7" 4 "0 -1 0"
+"k7" 4 "0 -1 0"
+"l7" 4 "0 -1 0"
+"m7" 4 "0 -1 0"
+"n7" 4 "0 -1 0"
+"o7" 4 "0 -1 0"
+"o6" 4 "0 -1 0"
+"n6" 4 "0 -1 0"
+"m6" 4 "0 -1 0"
+"l6" 4 "0 -1 0"
+"k6" 4 "0 -1 0"
+"j6" 4 "0 -1 0"
+"i6" 4 "0 -1 0"
+"h6" 4 "0 -1 0"
+"g6" 4 "0 -1 0"
+"f6" 4 "0 -1 0"
+"f5" 4 "0 -1 0"
+"g5" 4 "0 -1 0"
+"h5" 4 "0 -1 0"
+"i5" 4 "0 -1 0"
+"j5" 4 "0 -1 0"
+"k5" 4 "0 -1 0"
+"l5" 4 "0 -1 0"
+"m5" 4 "0 -1 0"
+"n5" 4 "0 -1 0"
+"o5" 4 "0 -1 0"
+"o4" 4 "0 -1 0"
+"n4" 4 "0 -1 0"
+"m4" 4 "0 -1 0"
+"l4" 4 "0 -1 0"
+"k4" 4 "0 -1 0"
+"j4" 4 "0 -1 0"
+"i4" 4 "0 -1 0"
+"h4" 4 "0 -1 0"
+"g4" 4 "0 -1 0"
+"f4" 4 "0 -1 0"
+"f3" 4 "0 -1 0"
+"g3" 4 "0 -1 0"
+"h3" 4 "0 -1 0"
+"i3" 4 "0 -1 0"
+"j3" 4 "0 -1 0"
+"k3" 4 "0 -1 0"
+"l3" 4 "0 -1 0"
+"m3" 4 "0 -1 0"
+"n3" 4 "0 -1 0"
+"o3" 4 "0 -1 0"
+"o2" 4 "0 -1 0"
+"n2" 4 "0 -1 0"
+"m2" 4 "0 -1 0"
+"l2" 4 "0 -1 0"
+"k2" 4 "0 -1 0"
+"j2" 4 "0 -1 0"
+"i2" 4 "0 -1 0"
+"h2" 4 "0 -1 0"
+"g2" 4 "0 -1 0"
+"f2" 4 "0 -1 0"
+"f1" 4 "0 -1 0"
+"g1" 4 "0 -1 0"
+"h1" 4 "0 -1 0"
+"i1" 4 "0 -1 0"
+"j1" 4 "0 -1 0"
+"k1" 4 "0 -1 0"
+"l1" 4 "0 -1 0"
+"m1" 4 "0 -1 0"
+"n1" 4 "0 -1 0"
+"o1" 4 "0 -1 0"
+"o8" 4 "0 -1 0"
+"o9" 4 "0 -1 0"
+"o10" 4 "0 -1 0"
+"o11" 4 "0 -1 0"
+"o12" 4 "0 -1 0"
+"o13" 4 "0 -1 0"
+"n13" 4 "0 -1 0"
+"n14" 4 "0 -1 0"
+"o14" 4 "0 -1 0"
+"o15" 4 "0 -1 0"
+"n15" 4 "0 -1 0"
+"m15" 4 "0 -1 0"
+"l15" 4 "0 -1 0"
+"o18" 4 "0 -1 0"
+"n18" 4 "0 -1 0"
+"m18" 4 "0 -1 0"
+"l18" 4 "0 -1 0"
+"k18" 4 "0 -1 0"
+"j18" 4 "0 -1 0"
+"i18" 4 "0 -1 0"
+"i19" 4 "0 -1 0"
+"h19" 4 "0 -1 0"
+"g19" 4 "0 -1 0"
+"f19" 4 "0 -1 0"
+"f20" 4 "0 -1 0"
+"g20" 4 "0 -1 0"
+"h20" 4 "0 -1 0"
+"i20" 4 "0 -1 0"
+"j20" 4 "0 -1 0"
+"k20" 4 "0 -1 0"
+"l20" 4 "0 -1 0"
+"m20" 4 "0 -1 0"
+"n20" 4 "0 -1 0"
+"o20" 4 "0 -1 0"
+"o19" 4 "0 -1 0"
+"n19" 4 "0 -1 0"
+"m19" 4 "0 -1 0"
+"l19" 4 "0 -1 0"
+"k19" 4 "0 -1 0"
+"j19" 4 "0 -1 0"
--- /dev/null
+// bulldozer storage "level8" last updated 06-12-2015 16:23:34
+nextlevel = "level9"
+"e13" 5 "0 -1 0"
+"e12" 5 "0 -1 0"
+"e11" 5 "0 -1 0"
+"e10" 5 "0 -1 0"
+"e9" 5 "0 -1 0"
+"f9" 5 "0 -1 0"
+"g9" 5 "0 -1 0"
+"h9" 5 "0 -1 0"
+"i10" 5 "0 -1 0"
+"i9" 5 "0 -1 0"
+"i11" 5 "0 -1 0"
+"j11" 5 "0 -1 0"
+"k11" 5 "0 -1 0"
+"l11" 5 "0 -1 0"
+"l10" 5 "0 -1 0"
+"l9" 5 "0 -1 0"
+"n9" 5 "0 -1 0"
+"m9" 5 "0 -1 0"
+"o9" 5 "0 -1 0"
+"o10" 5 "0 -1 0"
+"p10" 5 "0 -1 0"
+"p11" 5 "0 -1 0"
+"p12" 5 "0 -1 0"
+"o13" 5 "0 -1 0"
+"p13" 5 "0 -1 0"
+"o14" 5 "0 -1 0"
+"n14" 5 "0 -1 0"
+"l14" 5 "0 -1 0"
+"f14" 5 "0 -1 0"
+"g14" 5 "0 -1 0"
+"h14" 5 "0 -1 0"
+"i14" 5 "0 -1 0"
+"j14" 5 "0 -1 0"
+"m14" 5 "0 -1 0"
+"k14" 5 "0 -1 0"
+"f13" 5 "0 -1 0"
+"j13" 5 "0 -1 0"
+"i12" 2 "0 -1 0"
+"l12" 2 "0 -1 0"
+"j12" 2 "0 -1 0"
+"k12" 2 "0 -1 0"
+"h13" 1 "0 -1 0"
+"g12" 3 "0 -1 0"
+"h11" 3 "0 -1 0"
+"m12" 3 "0 -1 0"
+"n11" 3 "0 -1 0"
+"d13" 8 "0 -1 0"
+"d15" 8 "0 -1 0"
+"b16" 8 "0 -1 0"
+"b14" 8 "0 -1 0"
+"b12" 8 "0 -1 0"
+"b10" 8 "0 -1 0"
+"b8" 8 "0 -1 0"
+"d11" 8 "0 -1 0"
+"d9" 8 "0 -1 0"
+"d7" 8 "0 -1 0"
+"q10" 8 "0 -1 0"
+"q8" 8 "0 -1 0"
+"s15" 8 "0 -1 0"
+"s7" 8 "0 -1 0"
+"s9" 8 "0 -1 0"
+"s11" 8 "0 -1 0"
+"s13" 8 "0 -1 0"
+"q12" 8 "0 -1 0"
+"q14" 8 "0 -1 0"
+"q16" 8 "0 -1 0"
+"h17" 4 "0 -1 0"
+"g17" 4 "0 -1 0"
+"f17" 4 "0 -1 0"
+"e17" 4 "0 -1 0"
+"d17" 4 "0 -1 0"
+"c17" 4 "0 -1 0"
+"b17" 4 "0 -1 0"
+"a17" 4 "0 -1 0"
+"a16" 4 "0 -1 0"
+"a15" 4 "0 -1 0"
+"b15" 4 "0 -1 0"
+"c15" 4 "0 -1 0"
+"c14" 4 "0 -1 0"
+"d14" 4 "0 -1 0"
+"e14" 4 "0 -1 0"
+"e15" 4 "0 -1 0"
+"f15" 4 "0 -1 0"
+"g15" 4 "0 -1 0"
+"h15" 4 "0 -1 0"
+"i15" 4 "0 -1 0"
+"j15" 4 "0 -1 0"
+"k15" 4 "0 -1 0"
+"l15" 4 "0 -1 0"
+"m15" 4 "0 -1 0"
+"n15" 4 "0 -1 0"
+"o15" 4 "0 -1 0"
+"p15" 4 "0 -1 0"
+"q15" 4 "0 -1 0"
+"r15" 4 "0 -1 0"
+"r14" 4 "0 -1 0"
+"s14" 4 "0 -1 0"
+"t14" 4 "0 -1 0"
+"t13" 4 "0 -1 0"
+"t12" 4 "0 -1 0"
+"s12" 4 "0 -1 0"
+"r12" 4 "0 -1 0"
+"r11" 4 "0 -1 0"
+"q11" 4 "0 -1 0"
+"r10" 4 "0 -1 0"
+"s10" 4 "0 -1 0"
+"t10" 4 "0 -1 0"
+"t9" 4 "0 -1 0"
+"t8" 4 "0 -1 0"
+"s8" 4 "0 -1 0"
+"r8" 4 "0 -1 0"
+"r7" 4 "0 -1 0"
+"q7" 4 "0 -1 0"
+"p7" 4 "0 -1 0"
+"o7" 4 "0 -1 0"
+"n7" 4 "0 -1 0"
+"m7" 4 "0 -1 0"
+"l7" 4 "0 -1 0"
+"k7" 4 "0 -1 0"
+"j7" 4 "0 -1 0"
+"i7" 4 "0 -1 0"
+"h7" 4 "0 -1 0"
+"g7" 4 "0 -1 0"
+"f7" 4 "0 -1 0"
+"e7" 4 "0 -1 0"
+"e6" 4 "0 -1 0"
+"d6" 4 "0 -1 0"
+"c6" 4 "0 -1 0"
+"b6" 4 "0 -1 0"
+"a6" 4 "0 -1 0"
+"a5" 4 "0 -1 0"
+"b5" 4 "0 -1 0"
+"c5" 4 "0 -1 0"
+"d5" 4 "0 -1 0"
+"e5" 4 "0 -1 0"
+"f5" 4 "0 -1 0"
+"g5" 4 "0 -1 0"
+"h5" 4 "0 -1 0"
+"i5" 4 "0 -1 0"
+"j5" 4 "0 -1 0"
+"k5" 4 "0 -1 0"
+"l5" 4 "0 -1 0"
+"m5" 4 "0 -1 0"
+"n5" 4 "0 -1 0"
+"o5" 4 "0 -1 0"
+"p5" 4 "0 -1 0"
+"q5" 4 "0 -1 0"
+"r5" 4 "0 -1 0"
+"s5" 4 "0 -1 0"
+"t5" 4 "0 -1 0"
+"t4" 4 "0 -1 0"
+"s4" 4 "0 -1 0"
+"r4" 4 "0 -1 0"
+"q4" 4 "0 -1 0"
+"p4" 4 "0 -1 0"
+"o4" 4 "0 -1 0"
+"n4" 4 "0 -1 0"
+"m4" 4 "0 -1 0"
+"l4" 4 "0 -1 0"
+"k4" 4 "0 -1 0"
+"j4" 4 "0 -1 0"
+"i4" 4 "0 -1 0"
+"h4" 4 "0 -1 0"
+"g4" 4 "0 -1 0"
+"f4" 4 "0 -1 0"
+"e4" 4 "0 -1 0"
+"d4" 4 "0 -1 0"
+"c4" 4 "0 -1 0"
+"b4" 4 "0 -1 0"
+"a4" 4 "0 -1 0"
+"a3" 4 "0 -1 0"
+"b3" 4 "0 -1 0"
+"c3" 4 "0 -1 0"
+"d3" 4 "0 -1 0"
+"e3" 4 "0 -1 0"
+"f3" 4 "0 -1 0"
+"g3" 4 "0 -1 0"
+"h3" 4 "0 -1 0"
+"i3" 4 "0 -1 0"
+"j3" 4 "0 -1 0"
+"k3" 4 "0 -1 0"
+"l3" 4 "0 -1 0"
+"m3" 4 "0 -1 0"
+"n3" 4 "0 -1 0"
+"o3" 4 "0 -1 0"
+"p3" 4 "0 -1 0"
+"q3" 4 "0 -1 0"
+"r3" 4 "0 -1 0"
+"s3" 4 "0 -1 0"
+"t3" 4 "0 -1 0"
+"t2" 4 "0 -1 0"
+"s2" 4 "0 -1 0"
+"r2" 4 "0 -1 0"
+"q2" 4 "0 -1 0"
+"p2" 4 "0 -1 0"
+"o2" 4 "0 -1 0"
+"n2" 4 "0 -1 0"
+"m2" 4 "0 -1 0"
+"l2" 4 "0 -1 0"
+"k2" 4 "0 -1 0"
+"j2" 4 "0 -1 0"
+"i2" 4 "0 -1 0"
+"h2" 4 "0 -1 0"
+"g2" 4 "0 -1 0"
+"f2" 4 "0 -1 0"
+"e2" 4 "0 -1 0"
+"d2" 4 "0 -1 0"
+"c2" 4 "0 -1 0"
+"b2" 4 "0 -1 0"
+"a2" 4 "0 -1 0"
+"a1" 4 "0 -1 0"
+"b1" 4 "0 -1 0"
+"c1" 4 "0 -1 0"
+"d1" 4 "0 -1 0"
+"e1" 4 "0 -1 0"
+"f1" 4 "0 -1 0"
+"g1" 4 "0 -1 0"
+"h1" 4 "0 -1 0"
+"i1" 4 "0 -1 0"
+"j1" 4 "0 -1 0"
+"k1" 4 "0 -1 0"
+"l1" 4 "0 -1 0"
+"m1" 4 "0 -1 0"
+"n1" 4 "0 -1 0"
+"o1" 4 "0 -1 0"
+"p1" 4 "0 -1 0"
+"q1" 4 "0 -1 0"
+"r1" 4 "0 -1 0"
+"s1" 4 "0 -1 0"
+"t1" 4 "0 -1 0"
+"t6" 4 "0 -1 0"
+"s6" 4 "0 -1 0"
+"r6" 4 "0 -1 0"
+"q6" 4 "0 -1 0"
+"p6" 4 "0 -1 0"
+"o6" 4 "0 -1 0"
+"n6" 4 "0 -1 0"
+"m6" 4 "0 -1 0"
+"l6" 4 "0 -1 0"
+"k6" 4 "0 -1 0"
+"j6" 4 "0 -1 0"
+"i6" 4 "0 -1 0"
+"h6" 4 "0 -1 0"
+"g6" 4 "0 -1 0"
+"f6" 4 "0 -1 0"
+"t7" 4 "0 -1 0"
+"a7" 4 "0 -1 0"
+"b7" 4 "0 -1 0"
+"c7" 4 "0 -1 0"
+"c8" 4 "0 -1 0"
+"d8" 4 "0 -1 0"
+"e8" 4 "0 -1 0"
+"f8" 4 "0 -1 0"
+"g8" 4 "0 -1 0"
+"h8" 4 "0 -1 0"
+"i8" 4 "0 -1 0"
+"j8" 4 "0 -1 0"
+"k8" 4 "0 -1 0"
+"l8" 4 "0 -1 0"
+"m8" 4 "0 -1 0"
+"n8" 4 "0 -1 0"
+"o8" 4 "0 -1 0"
+"p8" 4 "0 -1 0"
+"p9" 4 "0 -1 0"
+"q9" 4 "0 -1 0"
+"r9" 4 "0 -1 0"
+"k9" 4 "0 -1 0"
+"j9" 4 "0 -1 0"
+"j10" 4 "0 -1 0"
+"k10" 4 "0 -1 0"
+"c9" 4 "0 -1 0"
+"b9" 4 "0 -1 0"
+"a9" 4 "0 -1 0"
+"a8" 4 "0 -1 0"
+"a10" 4 "0 -1 0"
+"a11" 4 "0 -1 0"
+"b11" 4 "0 -1 0"
+"c11" 4 "0 -1 0"
+"c10" 4 "0 -1 0"
+"d10" 4 "0 -1 0"
+"c12" 4 "0 -1 0"
+"d12" 4 "0 -1 0"
+"c13" 4 "0 -1 0"
+"b13" 4 "0 -1 0"
+"a13" 4 "0 -1 0"
+"a12" 4 "0 -1 0"
+"a14" 4 "0 -1 0"
+"t11" 4 "0 -1 0"
+"r13" 4 "0 -1 0"
+"q13" 4 "0 -1 0"
+"t15" 4 "0 -1 0"
+"t16" 4 "0 -1 0"
+"s16" 4 "0 -1 0"
+"r16" 4 "0 -1 0"
+"r17" 4 "0 -1 0"
+"q17" 4 "0 -1 0"
+"p17" 4 "0 -1 0"
+"o17" 4 "0 -1 0"
+"n17" 4 "0 -1 0"
+"m17" 4 "0 -1 0"
+"l17" 4 "0 -1 0"
+"k17" 4 "0 -1 0"
+"j17" 4 "0 -1 0"
+"i17" 4 "0 -1 0"
+"i16" 4 "0 -1 0"
+"h16" 4 "0 -1 0"
+"g16" 4 "0 -1 0"
+"f16" 4 "0 -1 0"
+"e16" 4 "0 -1 0"
+"d16" 4 "0 -1 0"
+"c16" 4 "0 -1 0"
+"j16" 4 "0 -1 0"
+"k16" 4 "0 -1 0"
+"l16" 4 "0 -1 0"
+"m16" 4 "0 -1 0"
+"n16" 4 "0 -1 0"
+"o16" 4 "0 -1 0"
+"p16" 4 "0 -1 0"
+"i18" 4 "0 -1 0"
+"h18" 4 "0 -1 0"
+"g18" 4 "0 -1 0"
+"f18" 4 "0 -1 0"
+"e18" 4 "0 -1 0"
+"d18" 4 "0 -1 0"
+"c18" 4 "0 -1 0"
+"b18" 4 "0 -1 0"
+"a18" 4 "0 -1 0"
+"a19" 4 "0 -1 0"
+"b19" 4 "0 -1 0"
+"c19" 4 "0 -1 0"
+"d19" 4 "0 -1 0"
+"e19" 4 "0 -1 0"
+"f19" 4 "0 -1 0"
+"g19" 4 "0 -1 0"
+"h19" 4 "0 -1 0"
+"i19" 4 "0 -1 0"
+"j19" 4 "0 -1 0"
+"k19" 4 "0 -1 0"
+"l19" 4 "0 -1 0"
+"m19" 4 "0 -1 0"
+"n19" 4 "0 -1 0"
+"o19" 4 "0 -1 0"
+"p19" 4 "0 -1 0"
+"q19" 4 "0 -1 0"
+"r19" 4 "0 -1 0"
+"s19" 4 "0 -1 0"
+"t19" 4 "0 -1 0"
+"t18" 4 "0 -1 0"
+"s18" 4 "0 -1 0"
+"r18" 4 "0 -1 0"
+"q18" 4 "0 -1 0"
+"p18" 4 "0 -1 0"
+"o18" 4 "0 -1 0"
+"n18" 4 "0 -1 0"
+"m18" 4 "0 -1 0"
+"l18" 4 "0 -1 0"
+"k18" 4 "0 -1 0"
+"j18" 4 "0 -1 0"
+"s17" 4 "0 -1 0"
+"t17" 4 "0 -1 0"
+"t20" 4 "0 -1 0"
+"s20" 4 "0 -1 0"
+"r20" 4 "0 -1 0"
+"q20" 4 "0 -1 0"
+"p20" 4 "0 -1 0"
+"o20" 4 "0 -1 0"
+"n20" 4 "0 -1 0"
+"m20" 4 "0 -1 0"
+"l20" 4 "0 -1 0"
+"k20" 4 "0 -1 0"
+"j20" 4 "0 -1 0"
+"i20" 4 "0 -1 0"
+"h20" 4 "0 -1 0"
+"g20" 4 "0 -1 0"
+"f20" 4 "0 -1 0"
+"e20" 4 "0 -1 0"
+"d20" 4 "0 -1 0"
+"c20" 4 "0 -1 0"
+"b20" 4 "0 -1 0"
+"a20" 4 "0 -1 0"
+"p14" 4 "0 -1 0"
--- /dev/null
+// bulldozer storage "level4" last updated 16-11-2015 04:16:07
+nextlevel = "level1"
+"e15" 3 "0 0 0"
+"f14" 3 "0 0 0"
+"g13" 3 "0 0 0"
+"k13" 3 "0 0 0"
+"b14" 4 "0 0 0"
+"a14" 4 "0 0 0"
+"a13" 4 "0 0 0"
+"b13" 4 "0 0 0"
+"i13" 3 "0 0 0"
+"m13" 3 "0 0 0"
+"n14" 3 "0 0 0"
+"o15" 3 "0 0 0"
+"h17" 2 "0 0 0"
+"l17" 2 "0 0 0"
+"c12" 2 "0 0 0"
+"c13" 2 "0 0 0"
+"c14" 2 "0 0 0"
+"r14" 2 "0 0 0"
+"r13" 2 "0 0 0"
+"r12" 2 "0 0 0"
+"j15" 1 "0 -1 0"
+"s13" 4 "0 0 0"
+"t13" 4 "0 0 0"
+"t12" 4 "0 0 0"
+"s12" 4 "0 0 0"
+"b12" 4 "0 0 0"
+"a12" 4 "0 0 0"
+"a11" 4 "0 0 0"
+"b11" 4 "0 0 0"
+"c11" 4 "0 0 0"
+"d11" 4 "0 0 0"
+"e11" 4 "0 0 0"
+"f11" 4 "0 0 0"
+"g11" 4 "0 0 0"
+"h11" 4 "0 0 0"
+"i11" 4 "0 0 0"
+"j11" 4 "0 0 0"
+"k11" 4 "0 0 0"
+"l11" 4 "0 0 0"
+"m11" 4 "0 0 0"
+"n11" 4 "0 0 0"
+"o11" 4 "0 0 0"
+"p11" 4 "0 0 0"
+"q11" 4 "0 0 0"
+"r11" 4 "0 0 0"
+"s11" 4 "0 0 0"
+"t11" 4 "0 0 0"
+"t6" 6 "0 0 0"
+"s10" 4 "0 0 0"
+"r10" 4 "0 0 0"
+"q10" 4 "0 0 0"
+"b10" 6 "0 0 0"
+"o10" 4 "0 0 0"
+"c10" 6 "0 0 0"
+"d10" 6 "0 0 0"
+"e6" 4 "0 0 0"
+"b9" 6 "0 0 0"
+"b8" 6 "0 0 0"
+"c7" 4 "0 0 0"
+"b7" 6 "0 0 0"
+"b6" 6 "0 0 0"
+"c6" 6 "0 0 0"
+"d6" 6 "0 0 0"
+"f10" 6 "0 0 0"
+"g10" 6 "0 0 0"
+"h10" 6 "0 0 0"
+"a10" 4 "0 0 0"
+"a9" 4 "0 0 0"
+"h9" 4 "0 0 0"
+"c9" 4 "0 0 0"
+"d9" 4 "0 0 0"
+"h8" 4 "0 0 0"
+"h7" 4 "0 0 0"
+"i10" 6 "0 0 0"
+"i9" 6 "0 0 0"
+"j7" 4 "0 0 0"
+"j6" 4 "0 0 0"
+"j10" 4 "0 0 0"
+"i8" 6 "0 0 0"
+"m9" 4 "0 0 0"
+"i7" 6 "0 0 0"
+"o9" 4 "0 0 0"
+"i6" 6 "0 0 0"
+"q9" 4 "0 0 0"
+"r9" 4 "0 0 0"
+"s9" 4 "0 0 0"
+"h6" 6 "0 0 0"
+"g6" 6 "0 0 0"
+"s8" 4 "0 0 0"
+"r8" 4 "0 0 0"
+"q8" 4 "0 0 0"
+"f6" 6 "0 0 0"
+"o8" 4 "0 0 0"
+"f7" 6 "0 0 0"
+"m8" 4 "0 0 0"
+"f8" 6 "0 0 0"
+"f9" 6 "0 0 0"
+"k10" 6 "0 0 0"
+"e10" 4 "0 0 0"
+"d7" 4 "0 0 0"
+"e9" 4 "0 0 0"
+"e8" 4 "0 0 0"
+"e7" 4 "0 0 0"
+"l10" 6 "0 0 0"
+"c8" 4 "0 0 0"
+"m10" 6 "0 0 0"
+"a8" 4 "0 0 0"
+"a7" 4 "0 0 0"
+"g7" 4 "0 0 0"
+"g8" 4 "0 0 0"
+"g9" 4 "0 0 0"
+"n10" 6 "0 0 0"
+"n9" 6 "0 0 0"
+"n8" 6 "0 0 0"
+"d8" 4 "0 0 0"
+"n7" 6 "0 0 0"
+"n6" 6 "0 0 0"
+"m6" 6 "0 0 0"
+"l6" 6 "0 0 0"
+"m7" 4 "0 0 0"
+"k6" 6 "0 0 0"
+"o7" 4 "0 0 0"
+"k7" 6 "0 0 0"
+"q7" 4 "0 0 0"
+"r7" 4 "0 0 0"
+"s7" 4 "0 0 0"
+"k8" 6 "0 0 0"
+"k9" 6 "0 0 0"
+"s6" 4 "0 0 0"
+"p9" 6 "0 0 0"
+"p8" 6 "0 0 0"
+"p7" 6 "0 0 0"
+"o6" 4 "0 0 0"
+"p6" 6 "0 0 0"
+"q6" 6 "0 0 0"
+"r6" 6 "0 0 0"
+"p10" 6 "0 0 0"
+"j9" 4 "0 0 0"
+"j8" 4 "0 0 0"
+"t10" 6 "0 0 0"
+"t9" 6 "0 0 0"
+"t8" 6 "0 0 0"
+"l7" 4 "0 0 0"
+"l8" 4 "0 0 0"
+"l9" 4 "0 0 0"
+"t7" 4 "0 0 0"
+"a6" 4 "0 0 0"
+"a5" 4 "0 0 0"
+"b5" 4 "0 0 0"
+"c5" 4 "0 0 0"
+"d5" 4 "0 0 0"
+"e5" 4 "0 0 0"
+"f5" 4 "0 0 0"
+"g5" 4 "0 0 0"
+"h5" 4 "0 0 0"
+"i5" 4 "0 0 0"
+"j5" 4 "0 0 0"
+"k5" 4 "0 0 0"
+"l5" 4 "0 0 0"
+"m5" 4 "0 0 0"
+"n5" 4 "0 0 0"
+"o5" 4 "0 0 0"
+"p5" 4 "0 0 0"
+"q5" 4 "0 0 0"
+"r5" 4 "0 0 0"
+"s5" 4 "0 0 0"
+"t5" 4 "0 0 0"
+"t4" 4 "0 0 0"
+"s4" 4 "0 0 0"
+"r4" 4 "0 0 0"
+"q4" 4 "0 0 0"
+"p4" 4 "0 0 0"
+"o4" 4 "0 0 0"
+"n4" 4 "0 0 0"
+"m4" 4 "0 0 0"
+"l4" 4 "0 0 0"
+"k4" 4 "0 0 0"
+"j4" 4 "0 0 0"
+"i4" 4 "0 0 0"
+"h4" 4 "0 0 0"
+"g4" 4 "0 0 0"
+"f4" 4 "0 0 0"
+"e4" 4 "0 0 0"
+"d4" 4 "0 0 0"
+"c4" 4 "0 0 0"
+"b4" 4 "0 0 0"
+"a4" 4 "0 0 0"
+"a3" 4 "0 0 0"
+"b3" 4 "0 0 0"
+"c3" 4 "0 0 0"
+"d3" 4 "0 0 0"
+"e3" 4 "0 0 0"
+"f3" 4 "0 0 0"
+"g3" 4 "0 0 0"
+"h3" 4 "0 0 0"
+"i3" 4 "0 0 0"
+"j3" 4 "0 0 0"
+"k3" 4 "0 0 0"
+"l3" 4 "0 0 0"
+"m3" 4 "0 0 0"
+"n3" 4 "0 0 0"
+"o3" 4 "0 0 0"
+"p3" 4 "0 0 0"
+"q3" 4 "0 0 0"
+"r3" 4 "0 0 0"
+"s3" 4 "0 0 0"
+"t3" 4 "0 0 0"
+"t2" 4 "0 0 0"
+"s2" 4 "0 0 0"
+"r2" 4 "0 0 0"
+"q2" 4 "0 0 0"
+"p2" 4 "0 0 0"
+"o2" 4 "0 0 0"
+"n2" 4 "0 0 0"
+"m2" 4 "0 0 0"
+"l2" 4 "0 0 0"
+"k2" 4 "0 0 0"
+"j2" 4 "0 0 0"
+"i2" 4 "0 0 0"
+"h2" 4 "0 0 0"
+"g2" 4 "0 0 0"
+"f2" 4 "0 0 0"
+"e2" 4 "0 0 0"
+"d2" 4 "0 0 0"
+"c2" 4 "0 0 0"
+"b2" 4 "0 0 0"
+"a2" 4 "0 0 0"
+"a1" 4 "0 0 0"
+"b1" 4 "0 0 0"
+"c1" 4 "0 0 0"
+"d1" 4 "0 0 0"
+"e1" 4 "0 0 0"
+"f1" 4 "0 0 0"
+"g1" 4 "0 0 0"
+"h1" 4 "0 0 0"
+"i1" 4 "0 0 0"
+"j1" 4 "0 0 0"
+"k1" 4 "0 0 0"
+"l1" 4 "0 0 0"
+"m1" 4 "0 0 0"
+"n1" 4 "0 0 0"
+"o1" 4 "0 0 0"
+"p1" 4 "0 0 0"
+"q1" 4 "0 0 0"
+"r1" 4 "0 0 0"
+"s1" 4 "0 0 0"
+"t1" 4 "0 0 0"
+"t14" 4 "0 0 0"
+"s14" 4 "0 0 0"
+"b15" 4 "0 0 0"
+"a15" 4 "0 0 0"
+"a16" 4 "0 0 0"
+"b16" 4 "0 0 0"
+"s16" 4 "0 0 0"
+"t16" 4 "0 0 0"
+"t15" 4 "0 0 0"
+"s15" 4 "0 0 0"
+"t17" 4 "0 0 0"
+"s17" 4 "0 0 0"
+"b17" 4 "0 0 0"
+"a17" 4 "0 0 0"
+"a18" 4 "0 0 0"
+"b18" 4 "0 0 0"
+"s18" 4 "0 0 0"
+"t18" 4 "0 0 0"
+"t19" 4 "0 0 0"
+"s19" 4 "0 0 0"
+"r19" 4 "0 0 0"
+"q19" 4 "0 0 0"
+"p19" 4 "0 0 0"
+"o19" 4 "0 0 0"
+"n19" 4 "0 0 0"
+"m19" 4 "0 0 0"
+"l19" 4 "0 0 0"
+"k19" 4 "0 0 0"
+"j19" 4 "0 0 0"
+"i19" 4 "0 0 0"
+"h19" 4 "0 0 0"
+"g19" 4 "0 0 0"
+"f19" 4 "0 0 0"
+"e19" 4 "0 0 0"
+"d19" 4 "0 0 0"
+"c19" 4 "0 0 0"
+"b19" 4 "0 0 0"
+"a19" 4 "0 0 0"
+"a20" 4 "0 0 0"
+"b20" 4 "0 0 0"
+"c20" 4 "0 0 0"
+"d20" 4 "0 0 0"
+"e20" 4 "0 0 0"
+"f20" 4 "0 0 0"
+"g20" 4 "0 0 0"
+"h20" 4 "0 0 0"
+"i20" 4 "0 0 0"
+"j20" 4 "0 0 0"
+"k20" 4 "0 0 0"
+"l20" 4 "0 0 0"
+"m20" 4 "0 0 0"
+"n20" 4 "0 0 0"
+"o20" 4 "0 0 0"
+"p20" 4 "0 0 0"
+"q20" 4 "0 0 0"
+"r20" 4 "0 0 0"
+"s20" 4 "0 0 0"
+"t20" 4 "0 0 0"
-fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
-frelaxed-switch -freturn-assignments \
$(QCCFLAGS_WATERMARK) \
+ -DNDEBUG=1 \
$(QCCFLAGS_FEATURES) \
$(QCCFLAGS_EXTRA)
{
SELFPARAM();
float starttime = STAT(GAMESTARTTIME);
- float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+ float roundstarttime = STAT(ROUNDSTARTTIME);
if(roundstarttime == -1)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
void Announcer_Gamestart()
{
float startTime = STAT(GAMESTARTTIME);
- float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+ float roundstarttime = STAT(ROUNDSTARTTIME);
if(roundstarttime > startTime)
startTime = roundstarttime;
// Plays the 1 minute or 5 minutes (of maptime) remaining sound, if client wants it
void Announcer_Time()
{
- float timelimit = getstatf(STAT_TIMELIMIT);
+ float timelimit = STAT(TIMELIMIT);
float timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
float warmup_timeleft = 0;
float uid2name_dialog;
-.bool csqcmodel_isdead; // used by shownames and miscfunctions (float getplayerisdead(float) {}) to know when a player is dead
+.bool csqcmodel_isdead; // used by shownames and miscfunctions (entcs_IsDead) to know when a player is dead
#define player_currententnum (spectatee_status > 0 ? spectatee_status : player_localnum + 1)
}
}
- t = GetPlayerColorForce(self.owner.sv_entnum);
+ t = entcs_GetTeamColor(self.owner.sv_entnum);
switch(self.HookType)
{
case NUM_TEAM_2: tex = "particles/hook_blue"; rgb = '0.3 0.3 1'; break;
case NUM_TEAM_3: tex = "particles/hook_yellow"; rgb = '1 1 0.3'; break;
case NUM_TEAM_4: tex = "particles/hook_pink"; rgb = '1 0.3 1'; break;
- default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum - 1); break;
+ default: tex = "particles/hook_white"; rgb = entcs_GetColor(self.sv_entnum - 1); break;
}
break;
case NET_ENT_CLIENT_ARC_BEAM: // todo
int ps_primary, ps_secondary;
int ts_primary, ts_secondary;
-int last_switchweapon;
-int last_activeweapon;
+Weapon last_switchweapon;
+Weapon last_activeweapon;
float weapontime;
float weaponprevtime;
}
int rows = 0, columns, row, column;
- float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
+ float nade_cnt = STAT(NADE_BONUS), nade_score = STAT(NADE_BONUS_SCORE);
bool draw_nades = (nade_cnt > 0 || nade_score > 0);
float nade_statuschange_elapsedtime;
int total_ammo_count;
ammo_size.y = newSize;
}
+ Weapon wep = switchweapon;
int i;
bool infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
row = column = 0;
DrawAmmoItem(
pos,
ammo_size,
- (get_weaponinfo(switchweapon)).ammo_field,
+ wep.ammo_field,
true,
infinite_ammo
);
pos + eX * column * (ammo_size.x + offset.x) + eY * row * (ammo_size.y + offset.y),
ammo_size,
ammotype,
- ((get_weaponinfo(switchweapon)).ammo_field == ammotype),
+ (wep.ammo_field == ammotype),
infinite_ammo
);
prev_health = 0;
prev_armor = 0;
}
- fuel = getstati(STAT_FUEL);
+ fuel = STAT(FUEL);
}
else
{
if(spectatee_status == -1)
s = _("^1Observing");
else
- s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(current_player));
+ s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
drawInfoMessage(s);
if(spectatee_status == -1)
switch(i)
{
case 0:
- stat = getstati(STAT_REDALIVE);
+ stat = STAT(REDALIVE);
pic = "player_red.tga";
color = '1 0 0';
break;
case 1:
- stat = getstati(STAT_BLUEALIVE);
+ stat = STAT(BLUEALIVE);
pic = "player_blue.tga";
color = '0 0 1';
break;
case 2:
- stat = getstati(STAT_YELLOWALIVE);
+ stat = STAT(YELLOWALIVE);
pic = "player_yellow.tga";
color = '1 1 0';
break;
default:
case 3:
- stat = getstati(STAT_PINKALIVE);
+ stat = STAT(PINKALIVE);
pic = "player_pink.tga";
color = '1 0 1';
break;
int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime, yellowflag_statuschange_elapsedtime, pinkflag_statuschange_elapsedtime, neutralflag_statuschange_elapsedtime; // time since the status changed
bool ctf_oneflag; // one-flag CTF mode enabled/disabled
- int stat_items = getstati(STAT_CTF_FLAGSTATUS, 0, 24);
+ int stat_items = STAT(CTF_FLAGSTATUS);
float fs, fs2, fs3, size1, size2;
vector e1, e2;
int stat_items;
stat_items = getstati(STAT_ITEMS, 0, 24);
- nb_pb_starttime = getstatf(STAT_NB_METERSTART);
+ nb_pb_starttime = STAT(NB_METERSTART);
if (stat_items & IT_KEY1)
mod_active = 1;
mod_active = 1; // race should never hide the mod icons panel
entity me;
me = playerslots[player_localnum];
- float t, score;
+ float score;
float f; // yet another function has this
score = me.(scores[ps_primary]);
rr = CTS_RECORD;
else
rr = RACE_RECORD;
- t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
+ float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
if(score && (score < t || !t)) {
db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
} else if(race_status == 2) {
- if(race_status_name == GetPlayerName(player_localnum) || !race_myrank || race_myrank < rank)
+ if(race_status_name == entcs_GetName(player_localnum) || !race_myrank || race_myrank < rank)
drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
else
drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
switch(i)
{
case 0:
- stat = getstatf(STAT_DOM_PPS_RED);
+ stat = STAT(DOM_PPS_RED);
pic = "dom_icon_red";
color = '1 0 0';
break;
case 1:
- stat = getstatf(STAT_DOM_PPS_BLUE);
+ stat = STAT(DOM_PPS_BLUE);
pic = "dom_icon_blue";
color = '0 0 1';
break;
case 2:
- stat = getstatf(STAT_DOM_PPS_YELLOW);
+ stat = STAT(DOM_PPS_YELLOW);
pic = "dom_icon_yellow";
color = '1 1 0';
break;
default:
case 3:
- stat = getstatf(STAT_DOM_PPS_PINK);
+ stat = STAT(DOM_PPS_PINK);
pic = "dom_icon_pink";
color = '1 0 1';
break;
}
- float pps_ratio = stat / getstatf(STAT_DOM_TOTAL_PPS);
+ float pps_ratio = stat / STAT(DOM_TOTAL_PPS);
if(mySize.x/mySize.y > aspect_ratio)
{
{
attacker = sprintf(_("Player %d"), count + 1);
victim = sprintf(_("Player %d"), count + 2);
- icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
+ icon = Weapons_from(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
alpha = bound(0, 1.2 - count / entry_count, 1);
}
else
void HUD_Powerups()
{
int allItems = getstati(STAT_ITEMS, 0, 24);
- int allBuffs = getstati(STAT_BUFFS, 0, 24);
+ int allBuffs = STAT(BUFFS);
int strengthTime, shieldTime, superTime;
// Initialize items
strengthTime = bound(0, STAT(STRENGTH_FINISHED) - time, 99);
shieldTime = bound(0, STAT(INVINCIBLE_FINISHED) - time, 99);
- superTime = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
+ superTime = bound(0, STAT(SUPERWEAPONS_FINISHED) - time, 99);
if(allItems & IT_UNLIMITED_SUPERWEAPONS)
superTime = 99;
vector keysize;
keysize = eX * mySize.x * (1/3.0) + eY * mySize.y * (1/(3.0 - !autocvar_hud_panel_pressedkeys_attack));
- float pressedkeys;
- pressedkeys = getstatf(STAT_PRESSED_KEYS);
+ int pressedkeys = STAT(PRESSED_KEYS);
if(autocvar_hud_panel_pressedkeys_attack)
{
}
int color2;
- entity tm;
float scale2d, normalsize, bigsize;
teamradar_origin2d = pos + 0.5 * mySize;
draw_teamradar_background(hud_panel_radar_foreground_alpha);
- for(tm = world; (tm = find(tm, classname, "radarlink")); )
- draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+ FOREACH_ENTITY_CLASS("radarlink", true, LAMBDA(
+ draw_teamradar_link(it.origin, it.velocity, it.team);
+ ));
- vector coord;
- vector brightcolor;
- for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
- {
+ FOREACH_ENTITY_FLAGS(teamradar_icon, 0xFFFFFF, LAMBDA(
if ( hud_panel_radar_mouse )
- if ( tm.health > 0 )
- if ( tm.team == myteam+1 )
+ if ( it.health > 0 )
+ if ( it.team == myteam+1 )
{
- coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
+ vector coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(it.origin));
if ( vlen(mousepos-coord) < 8 )
{
- brightcolor_x = min(1,tm.teamradar_color_x*1.5);
- brightcolor_y = min(1,tm.teamradar_color_y*1.5);
- brightcolor_z = min(1,tm.teamradar_color_z*1.5);
+ vector brightcolor;
+ brightcolor_x = min(1,it.teamradar_color_x*1.5);
+ brightcolor_y = min(1,it.teamradar_color_y*1.5);
+ brightcolor_z = min(1,it.teamradar_color_z*1.5);
drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
}
}
- entity icon = RadarIcons_from(tm.teamradar_icon);
- draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
- }
- for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
- {
- if (!tm.m_entcs_private) continue;
- if (entcs_is_self(tm)) continue;
- color2 = GetPlayerColor(tm.sv_entnum);
- //if(color == NUM_SPECTATOR || color == color2)
- draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
- }
+ entity icon = RadarIcons_from(it.teamradar_icon);
+ draw_teamradar_icon(it.origin, icon, it, spritelookupcolor(it, icon.netname, it.teamradar_color), panel_fg_alpha);
+ ));
+ AL_EACH(_entcs, e, it != NULL, LAMBDA(
+ if (!it.m_entcs_private) continue;
+ if (entcs_is_self(it)) continue;
+ color2 = entcs_GetTeam(it.sv_entnum);
+ draw_teamradar_player(it.origin, it.angles, Team_ColorRGB(color2));
+ ));
draw_teamradar_player(view_origin, view_angles, '1 1 1');
drawresetcliparea();
{
rgb = '1 1 0';
drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
- s = GetPlayerName(player_localnum);
+ s = entcs_GetName(player_localnum);
score = 7;
}
else
}
if (team_count)
score_color = Team_ColorRGB(pl.team) * 0.8;
- s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
+ s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
pos.y += fontsize.y;
string timer;
float timelimit, elapsedTime, timeleft, minutesLeft;
- timelimit = getstatf(STAT_TIMELIMIT);
+ timelimit = STAT(TIMELIMIT);
timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
timeleft = ceil(timeleft);
weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " ");
weapon_cnt = 0;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- setself(get_weaponinfo(i));
- if(self.impulse >= 0)
- {
- weaponorder[weapon_cnt] = self;
- ++weapon_cnt;
- }
- }
+ FOREACH(Weapons, it != WEP_Null && it.impulse >= 0, LAMBDA(weaponorder[weapon_cnt++] = it));
for(i = weapon_cnt; i < Weapons_MAX; ++i)
- weaponorder[i] = world;
- heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world);
+ weaponorder[i] = NULL;
+ heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, NULL);
weaponorder_cmp_str = string_null;
}
{
if(!weapons_stat)
for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
- weapons_stat |= WepSet_FromWeapon(i);
+ weapons_stat |= WepSet_FromWeapon(Weapons_from(i));
#if 0
/// debug code
weapons_stat = '0 0 0';
float countw = 1 + floor((floor(time * cvar("wep_add"))) % (Weapons_COUNT - 1));
for(i = WEP_FIRST; i <= countw; ++i)
- weapons_stat |= WepSet_FromWeapon(i);
+ weapons_stat |= WepSet_FromWeapon(Weapons_from(i));
}
#endif
}
// do we own this weapon?
weapon_count = 0;
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
- if((weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon)) || (weaponorder[i].weapon == complain_weapon))
+ if((weapons_stat & WepSet_FromWeapon(Weapons_from(weaponorder[i].weapon))) || (weaponorder[i].weapon == complain_weapon))
++weapon_count;
// get the all-weapons layout
int nHidden = 0;
WepSet weapons_stat = WepSet_GetFromStat();
- for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- Weapon w = get_weaponinfo(i);
- if (weapons_stat & w.m_wepset) continue;
- if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
- }
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ if (weapons_stat & it.m_wepset) continue;
+ if (it.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
+ ));
vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
columns = table_size.x;
rows = table_size.y;
// retrieve information about the current weapon to be drawn
setself(weaponorder[i]);
weapon_id = self.impulse;
- isCurrent = (self.weapon == switchweapon);
+ isCurrent = (self.weapon == switchweapon.m_id);
// skip if this weapon doesn't exist
if(!self || weapon_id < 0) { continue; }
// skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
if(autocvar_hud_panel_weapons_onlyowned)
- if (!((weapons_stat & WepSet_FromWeapon(self.weapon)) || (self.weapon == complain_weapon)))
+ if (!((weapons_stat & WepSet_FromWeapon(Weapons_from(self.weapon))) || (self.weapon == complain_weapon)))
continue;
// figure out the drawing position of weapon
}
// drawing all the weapon items
- if(weapons_stat & WepSet_FromWeapon(self.weapon))
+ if(weapons_stat & WepSet_FromWeapon(Weapons_from(self.weapon)))
{
// draw the weapon image
if(isCurrent)
for(i = 0; i < maxclients; ++i)
{
e = playerslots[i];
- if(GetPlayerName(i) == "")
+ if(entcs_GetName(i) == "")
{
if(e.sort_prev)
{
e.ping_packetloss = 0;
e.ping_movementloss = 0;
//e.gotscores = 0; // we might already have the scores...
- SetTeam(e, GetPlayerColor(i)); // will not hurt; later updates come with HUD_UpdatePlayerTeams
+ SetTeam(e, entcs_GetTeam(i)); // will not hurt; later updates come with HUD_UpdatePlayerTeams
RegisterPlayer(e);
HUD_UpdatePlayerPos(e);
}
if(is_new)
{
- float teamnum = GetPlayerColor(entnum - 1);
+ float teamnum = entcs_GetTeam(entnum - 1);
if(autocvar_cl_spawn_event_particles)
{
else
{
serverprevtime = time;
- serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
time = serverprevtime + serverdeltatime;
}
strunzone(grecordholder[pos-1]);
grecordholder[pos-1] = strzone(ReadString());
grecordtime[pos-1] = ReadInt24_t();
- if(grecordholder[pos-1] == GetPlayerName(player_localnum))
+ if(grecordholder[pos-1] == entcs_GetName(player_localnum))
race_myrank = pos;
break;
case RACE_NET_SERVER_STATUS:
#define CLIENT_MAIN_H
#include "../common/constants.qh"
+#include "../common/weapons/all.qh"
// --------------------------------------------------------------------------
// MENU Functionality
bool spectatorbutton_zoom;
bool button_attack2;
-int activeweapon;
-int switchingweapon;
-#define switchweapon STAT(SWITCHWEAPON)
+Weapon activeweapon;
+Weapon switchingweapon;
+Weapon switchweapon;
float current_viewzoom;
float zoomin_effect;
float warmup_stage;
#include "weapons/projectile.qc" // TODO
+#include "../common/anim.qc"
#include "../common/animdecide.qc"
#include "../common/effects/effectinfo.qc"
#include "../common/ent_cs.qc"
#include "../common/deathtypes/all.qc"
#include "../common/effects/all.qc"
#include "../common/gamemodes/all.qc"
+#include "../common/impulses/all.qc"
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
#include "../common/mutators/all.qc"
#include "../lib/warpzone/anglestransform.qc"
#include "../lib/warpzone/client.qc"
#include "../lib/warpzone/common.qc"
+#include "../lib/warpzone/server.qc"
#include "../lib/warpzone/util_server.qc"
#if BUILD_MOD
continue;
if(without_me && pl.sv_entnum == player_localnum)
continue;
- QUICKMENU_ENTRY(GetPlayerName(pl.sv_entnum), sprintf(cmd, GetPlayerName(pl.sv_entnum)))
+ QUICKMENU_ENTRY(entcs_GetName(pl.sv_entnum), sprintf(cmd, entcs_GetName(pl.sv_entnum)))
}
return;
QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
QUICKMENU_ENTRY(CTX(_("QMCMD^Restart the map")), "vcall restart")
QUICKMENU_ENTRY(CTX(_("QMCMD^End match")), "vcall endmatch")
- if(getstatf(STAT_TIMELIMIT) > 0)
+ if(STAT(TIMELIMIT) > 0)
{
QUICKMENU_ENTRY(CTX(_("QMCMD^Reduce match time")), "vcall reducematchtime")
QUICKMENU_ENTRY(CTX(_("QMCMD^Extend match time")), "vcall extendmatchtime")
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
num += 1;
- Team = GetPlayerColor(pl.sv_entnum);
+ Team = entcs_GetTeam(pl.sv_entnum);
if(SetTeam(pl, Team))
{
tmp = pl.sort_prev;
float HUD_ComparePlayerScores(entity left, entity right)
{
float vl, vr, r;
- vl = GetPlayerColor(left.sv_entnum);
- vr = GetPlayerColor(right.sv_entnum);
+ vl = entcs_GetTeam(left.sv_entnum);
+ vr = entcs_GetTeam(right.sv_entnum);
if(!left.gotscores)
vl = NUM_SPECTATOR;
hud_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
}
}
- return GetPlayerName(pl.sv_entnum);
+ return entcs_GetName(pl.sv_entnum);
case SP_FRAGS:
f = pl.(scores[SP_KILLS]);
string str;
int field;
float is_spec;
- is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
+ is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
if((rgb == '1 1 1') && (!is_spec)) {
rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
WepSet weapons_inmap = WepSet_GetFromStat_InMap();
float initial_posx = pos.x;
int disownedcnt = 0;
- for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- Weapon e = get_weaponinfo(i);
- setself(e);
- if (!self.weapon) continue;
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ if (!it.weapon) continue;
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
- WepSet set = e.m_wepset;
+ WepSet set = it.m_wepset;
if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
++disownedcnt;
- }
+ ));
int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
if (weapon_cnt <= 0) return pos;
vector tmpos = pos;
int column = 0;
- for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- Weapon e = get_weaponinfo(i);
- setself(e);
- if (!self.weapon) continue;
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ if (!it.weapon) continue;
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
- WepSet set = e.m_wepset;
+ WepSet set = it.m_wepset;
if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
continue;
weapon_alpha = 0.2 * scoreboard_alpha_fg;
// weapon icon
- drawpic_aspect_skin(tmpos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(tmpos, it.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
// the accuracy
if (weapon_stats >= 0) {
weapons_with_stats += 1;
pos.y += height;
}
++column;
- }
+ ));
if (weapons_with_stats)
average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
string val;
// get monster stats
- stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
- stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
+ stat_monsters_killed = STAT(MONSTERS_KILLED);
+ stat_monsters_total = STAT(MONSTERS_TOTAL);
// get secrets stats
- stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
- stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
+ stat_secrets_found = STAT(SECRETS_FOUND);
+ stat_secrets_total = STAT(SECRETS_TOTAL);
// get number of rows
if(stat_secrets_total)
return pos;
float is_spec;
- is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
+ is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
vector hl_rgb;
hl_rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
hl_rgb.y = autocvar_scoreboard_color_bg_g + 0.5;
continue;
n = grecordholder[i];
p = count_ordinal(i+1);
- if(grecordholder[i] == GetPlayerName(player_localnum))
+ if(grecordholder[i] == entcs_GetName(player_localnum))
drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
else if(!(i % 2) && scoreboard_highlight)
drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
// Print info string
float tl, fl, ll;
str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
- tl = getstatf(STAT_TIMELIMIT);
- fl = getstatf(STAT_FRAGLIMIT);
- ll = getstatf(STAT_LEADLIMIT);
+ tl = STAT(TIMELIMIT);
+ fl = STAT(FRAGLIMIT);
+ ll = STAT(LEADLIMIT);
if(gametype == MAPINFO_TYPE_LMS)
{
if(tl > 0)
drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
// print information about respawn status
- float respawn_time = getstatf(STAT_RESPAWN_TIME);
+ float respawn_time = STAT(RESPAWN_TIME);
if(!intermission)
if(respawn_time)
{
for (int i = 0; i < maxclients; ++i)
{
entity e = new(shownames_tag);
+ make_pure(e);
e.sv_entnum = i + 1;
LL_PUSH(shownames_ent, e);
}
// multiply by player alpha
if (!this.sameteam || (this.sv_entnum == player_localentnum))
{
- float f = getplayeralpha(this.sv_entnum - 1);
+ float f = entcs_GetAlpha(this.sv_entnum - 1);
if (f == 0) f = 1;
if (f < 0) f = 0;
// FIXME: alpha is negative when dead, breaking death fade
DRAWFLAG_NORMAL);
}
}
- string s = GetPlayerName(this.sv_entnum - 1);
+ string s = entcs_GetName(this.sv_entnum - 1);
if ((autocvar_hud_shownames_decolorize == 1 && teamplay)
- || autocvar_hud_shownames_decolorize == 2) s = playername(s, GetPlayerColor(this.sv_entnum - 1));
+ || autocvar_hud_shownames_decolorize == 2) s = playername(s, entcs_GetTeam(this.sv_entnum - 1));
drawfontscale = '1 1 0' * resize;
s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
if (!autocvar_hud_shownames) return;
LL_EACH(shownames_ent, true, LAMBDA(
entity entcs = entcs_receiver(i);
- if (!entcs) continue;
+ if (!entcs)
+ {
+ make_pure(it);
+ continue;
+ }
+ make_impure(it);
+ assert(entcs.think, eprint(entcs));
+ WITH(entity, self, entcs, entcs.think());
+ if (!entcs.has_origin) continue;
if (entcs.m_entcs_private)
{
it.healthvalue = entcs.healthvalue;
it.armorvalue = 0;
it.sameteam = false;
}
- bool dead = getplayerisdead(i);
- if (!it.csqcmodel_isdead && entcs.has_origin) setorigin(it, entcs.origin);
+ bool dead = entcs_IsDead(i) || entcs_IsSpectating(i);
+ if (!it.csqcmodel_isdead) setorigin(it, entcs.origin);
it.csqcmodel_isdead = dead;
Draw_ShowNames(it);
));
#include "mutators/events.qh"
+#include "../common/anim.qh"
#include "../common/constants.qh"
#include "../common/debug.qh"
#include "../common/mapinfo.qh"
#include "../lib/warpzone/client.qh"
#include "../lib/warpzone/common.qh"
+#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
+
+float autocvar_cl_viewmodel_scale;
+
+bool autocvar_cl_bobmodel;
+float autocvar_cl_bobmodel_speed;
+float autocvar_cl_bobmodel_side;
+float autocvar_cl_bobmodel_up;
+
+float autocvar_cl_followmodel;
+float autocvar_cl_followmodel_side_speed;
+float autocvar_cl_followmodel_side_highpass;
+float autocvar_cl_followmodel_side_highpass1;
+float autocvar_cl_followmodel_side_limit;
+float autocvar_cl_followmodel_side_lowpass;
+float autocvar_cl_followmodel_up_speed;
+float autocvar_cl_followmodel_up_highpass;
+float autocvar_cl_followmodel_up_highpass1;
+float autocvar_cl_followmodel_up_limit;
+float autocvar_cl_followmodel_up_lowpass;
+
+float autocvar_cl_leanmodel;
+float autocvar_cl_leanmodel_side_speed;
+float autocvar_cl_leanmodel_side_highpass;
+float autocvar_cl_leanmodel_side_highpass1;
+float autocvar_cl_leanmodel_side_lowpass;
+float autocvar_cl_leanmodel_side_limit;
+float autocvar_cl_leanmodel_up_speed;
+float autocvar_cl_leanmodel_up_highpass;
+float autocvar_cl_leanmodel_up_highpass1;
+float autocvar_cl_leanmodel_up_lowpass;
+float autocvar_cl_leanmodel_up_limit;
+
+#define lowpass(value, frac, ref_store, ret) do \
+{ \
+ float __frac = bound(0, frac, 1); \
+ ret = ref_store = ref_store * (1 - __frac) + (value) * __frac; \
+} while (0)
+
+#define lowpass_limited(value, frac, limit, ref_store, ret) do \
+{ \
+ float __ignore; lowpass(value, frac, ref_store, __ignore); \
+ ret = ref_store = bound((value) - (limit), ref_store, (value) + (limit)); \
+} while (0)
+
+#define highpass(value, frac, ref_store, ret) do \
+{ \
+ float __f; lowpass(value, frac, ref_store, __f); \
+ ret = (value) - __f; \
+} while (0)
+
+#define highpass_limited(value, frac, limit, ref_store, ret) do \
+{ \
+ float __f; lowpass_limited(value, frac, limit, ref_store, __f); \
+ ret = (value) - __f; \
+} while (0)
+
+#define lowpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
+{ \
+ lowpass(value.x, fracx, ref_store.x, ref_out.x); \
+ lowpass(value.y, fracy, ref_store.y, ref_out.y); \
+ lowpass(value.z, fracz, ref_store.z, ref_out.z); \
+} while (0)
+
+#define highpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
+{ \
+ highpass(value.x, fracx, ref_store.x, ref_out.x); \
+ highpass(value.y, fracy, ref_store.y, ref_out.y); \
+ highpass(value.z, fracz, ref_store.z, ref_out.z); \
+} while (0)
+
+#define highpass3_limited(value, fracx, limitx, fracy, limity, fracz, limitz, ref_store, ref_out) do \
+{ \
+ highpass_limited(value.x, fracx, limitx, ref_store.x, ref_out.x); \
+ highpass_limited(value.y, fracy, limity, ref_store.y, ref_out.y); \
+ highpass_limited(value.z, fracz, limitz, ref_store.z, ref_out.z); \
+} while (0)
+
+void viewmodel_animate(entity this)
+{
+ static float prevtime;
+ float frametime = (time - prevtime) * STAT(MOVEVARS_TIMESCALE);
+ prevtime = time;
+
+ if (autocvar_chase_active) return;
+ if (getstati(STAT_HEALTH) <= 0) return;
+
+ entity view = CSQCModel_server2csqc(player_localentnum - 1);
+
+ bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
+ static bool oldonground;
+ static float hitgroundtime;
+ static float lastongroundtime;
+ if (clonground)
+ {
+ float f = time; // cl.movecmd[0].time
+ if (!oldonground)
+ hitgroundtime = f;
+ lastongroundtime = f;
+ }
+ oldonground = clonground;
+
+ vector gunorg = '0 0 0', gunangles = '0 0 0';
+ static vector gunorg_prev = '0 0 0', gunangles_prev = '0 0 0';
+
+ bool teleported = view.csqcmodel_teleported;
+
+ // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
+ if (teleported)
+ {
+ // try to fix the first highpass; result is NOT
+ // perfect! TODO find a better fix
+ gunangles_prev = view_angles;
+ gunorg_prev = view_origin;
+ }
+
+ static vector gunorg_highpass = '0 0 0';
+
+ // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
+ gunorg_highpass += gunorg_prev;
+ highpass3_limited(view_origin,
+ frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
+ frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
+ frametime * autocvar_cl_followmodel_up_highpass1, autocvar_cl_followmodel_up_limit,
+ gunorg_highpass, gunorg);
+ gunorg_prev = view_origin;
+ gunorg_highpass -= gunorg_prev;
+
+ static vector gunangles_highpass = '0 0 0';
+
+ // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
+ gunangles_highpass += gunangles_prev;
+ PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
+ YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
+ ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
+ highpass3_limited(view_angles,
+ frametime * autocvar_cl_leanmodel_up_highpass1, autocvar_cl_leanmodel_up_limit,
+ frametime * autocvar_cl_leanmodel_side_highpass1, autocvar_cl_leanmodel_side_limit,
+ 0, 0,
+ gunangles_highpass, gunangles);
+ gunangles_prev = view_angles;
+ gunangles_highpass -= gunangles_prev;
+
+ // 3. calculate the RAW adjustment vectors
+ gunorg.x *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
+ gunorg.y *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
+ gunorg.z *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_up_speed : 0);
+
+ PITCH(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_up_speed : 0);
+ YAW(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_side_speed : 0);
+ ROLL(gunangles) = 0;
+
+ static vector gunorg_adjustment_highpass;
+ static vector gunorg_adjustment_lowpass;
+ static vector gunangles_adjustment_highpass;
+ static vector gunangles_adjustment_lowpass;
+
+ // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
+ // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
+ highpass3(gunorg,
+ frametime * autocvar_cl_followmodel_side_highpass,
+ frametime * autocvar_cl_followmodel_side_highpass,
+ frametime * autocvar_cl_followmodel_up_highpass,
+ gunorg_adjustment_highpass, gunorg);
+ lowpass3(gunorg,
+ frametime * autocvar_cl_followmodel_side_lowpass,
+ frametime * autocvar_cl_followmodel_side_lowpass,
+ frametime * autocvar_cl_followmodel_up_lowpass,
+ gunorg_adjustment_lowpass, gunorg);
+ // we assume here: PITCH = 0, YAW = 1, ROLL = 2
+ highpass3(gunangles,
+ frametime * autocvar_cl_leanmodel_up_highpass,
+ frametime * autocvar_cl_leanmodel_side_highpass,
+ 0,
+ gunangles_adjustment_highpass, gunangles);
+ lowpass3(gunangles,
+ frametime * autocvar_cl_leanmodel_up_lowpass,
+ frametime * autocvar_cl_leanmodel_side_lowpass,
+ 0,
+ gunangles_adjustment_lowpass, gunangles);
+ float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
+
+ // vertical view bobbing code
+ // TODO: cl_bob
+
+ // horizontal view bobbing code
+ // TODO: cl_bob2
+
+ // fall bobbing code
+ // causes the view to swing down and back up when touching the ground
+ // TODO: cl_bobfall
+
+ // gun model bobbing code
+ if (autocvar_cl_bobmodel)
+ {
+ // calculate for swinging gun model
+ // the gun bobs when running on the ground, but doesn't bob when you're in the air.
+ // Sajt: I tried to smooth out the transitions between bob and no bob, which works
+ // for the most part, but for some reason when you go through a message trigger or
+ // pick up an item or anything like that it will momentarily jolt the gun.
+ vector forward, right, up;
+ float bspeed;
+ float t = 1;
+ float s = time * autocvar_cl_bobmodel_speed;
+ if (clonground)
+ {
+ if (time - hitgroundtime < 0.2)
+ {
+ // just hit the ground, speed the bob back up over the next 0.2 seconds
+ t = time - hitgroundtime;
+ t = bound(0, t, 0.2);
+ t *= 5;
+ }
+ }
+ else
+ {
+ // recently left the ground, slow the bob down over the next 0.2 seconds
+ t = time - lastongroundtime;
+ t = 0.2 - bound(0, t, 0.2);
+ t *= 5;
+ }
+ bspeed = xyspeed * 0.01;
+ MAKEVECTORS(makevectors, view_angles, forward, right, up);
+ float bobr = bspeed * autocvar_cl_bobmodel_side * autocvar_cl_viewmodel_scale * sin(s) * t;
+ gunorg += bobr * right;
+ float bobu = bspeed * autocvar_cl_bobmodel_up * autocvar_cl_viewmodel_scale * cos(s * 2) * t;
+ gunorg += bobu * up;
+ }
+ vector v = rotate(gunorg, YAW(view_angles) * DEG2RAD); // rotate world coordinates to relative ones
+ v.z = gunorg.z;
+ this.origin += v;
+ gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
+ this.angles += gunangles;
+}
+
+.vector viewmodel_origin, viewmodel_angles;
+.float weapon_nextthink;
+.float weapon_eta_last;
+.float weapon_switchdelay;
+
+void viewmodel_draw(entity this)
+{
+ int mask = (intermission || (getstati(STAT_HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
+ float a = this.alpha;
+ int c = stof(getplayerkeyvalue(current_player, "colors"));
+ vector g;
+ Weapon wep = activeweapon;
+ if (!(g = wep.wr_glow(wep))) g = colormapPaletteColor(c & 0x0F, true) * 2;
+ entity me = CSQCModel_server2csqc(player_localentnum - 1);
+ int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
+ | EF_NODEPTHTEST)
+ &~ (EF_FULLBRIGHT); // can mask team color, so get rid of it
+ for (entity e = this; e; e = e.weaponchild)
+ {
+ e.drawmask = mask;
+ e.alpha = a;
+ e.colormap = 256 + c; // colormap == 0 is black, c == 0 is white
+ e.glowmod = g;
+ e.csqcmodel_effects = fx;
+ WITH(entity, self, e, CSQCModel_Effects_Apply());
+ }
+ {
+ static string name_last;
+ string name = wep.mdl;
+ if (name != name_last)
+ {
+ name_last = name;
+ CL_WeaponEntity_SetModel(this, name);
+ this.viewmodel_origin = this.origin;
+ this.viewmodel_angles = this.angles;
+ }
+ anim_update(this);
+ if (!this.animstate_override)
+ anim_set(this, this.anim_idle, true, false, false);
+ }
+ float f = 0; // 0..1; 0: fully active
+ float eta = (this.weapon_nextthink - time) / STAT(WEAPONRATEFACTOR);
+ if (eta <= 0) f = this.weapon_eta_last;
+ else switch (this.state)
+ {
+ case WS_RAISE:
+ {
+ f = eta / max(eta, this.weapon_switchdelay);
+ break;
+ }
+ case WS_DROP:
+ {
+ f = 1 - eta / max(eta, this.weapon_switchdelay);
+ break;
+ }
+ case WS_CLEAR:
+ {
+ f = 1;
+ break;
+ }
+ }
+ this.weapon_eta_last = f;
+ this.origin = this.viewmodel_origin;
+ this.angles = this.viewmodel_angles;
+ this.angles_x = (-90 * f * f);
+ viewmodel_animate(this);
+ setorigin(this, this.origin);
+}
+
+entity viewmodel;
+STATIC_INIT(viewmodel) {
+ viewmodel = new(viewmodel);
+ make_pure(viewmodel);
+ viewmodel.draw = viewmodel_draw;
+}
+
entity porto;
vector polyline[16];
void Porto_Draw(entity this)
vector p, dir, ang, q, nextdir;
float portal_number, portal1_idx;
- if(activeweapon != WEP_PORTO.m_id || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL)
+ if(activeweapon != WEP_PORTO || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL)
return;
if(g_balance_porto_secondary)
return;
zoomdir = button_zoom;
if(hud == HUD_NORMAL)
if(switchweapon == activeweapon)
- if((activeweapon == WEP_VORTEX.m_id && vortex_scope) || (activeweapon == WEP_RIFLE.m_id && rifle_scope)) // do NOT use switchweapon here
+ if((activeweapon == WEP_VORTEX && vortex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
zoomdir += button_attack2;
if(spectatee_status > 0 || isdemo())
{
return SHOTTYPE_HITWORLD;
if(n > maxclients)
return SHOTTYPE_HITWORLD;
- t = GetPlayerColor(n - 1);
+ t = entcs_GetTeam(n - 1);
if(teamplay)
if(t == myteam)
return SHOTTYPE_HITTEAM;
switch(activeweapon) // WEAPONTODO
{
- case WEP_TUBA.m_id: // no aim
- case WEP_PORTO.m_id: // shoots from eye
- case WEP_NEXBALL.m_id: // shoots from eye
- case WEP_HOOK.m_id: // no trueaim
- case WEP_MORTAR.m_id: // toss curve
+ case WEP_TUBA: // no aim
+ case WEP_PORTO: // shoots from eye
+ case WEP_NEXBALL: // shoots from eye
+ case WEP_HOOK: // no trueaim
+ case WEP_MORTAR: // toss curve
return SHOTTYPE_HITWORLD;
- case WEP_VORTEX.m_id:
- case WEP_VAPORIZER.m_id:
+ case WEP_VORTEX:
+ case WEP_VAPORIZER:
mv = MOVE_NORMAL;
break;
- case WEP_RIFLE.m_id:
+ case WEP_RIFLE:
ta = trueaim_rifle;
mv = MOVE_NORMAL;
if(zoomscript_caught)
return EnemyHitCheck();
}
break;
- case WEP_DEVASTATOR.m_id: // projectile has a size!
+ case WEP_DEVASTATOR: // projectile has a size!
mi = '-3 -3 -3';
ma = '3 3 3';
break;
- case WEP_FIREBALL.m_id: // projectile has a size!
+ case WEP_FIREBALL: // projectile has a size!
mi = '-16 -16 -16';
ma = '16 16 16';
break;
- case WEP_SEEKER.m_id: // projectile has a size!
+ case WEP_SEEKER: // projectile has a size!
mi = '-2 -2 -2';
ma = '2 2 2';
break;
- case WEP_ELECTRO.m_id: // projectile has a size!
+ case WEP_ELECTRO: // projectile has a size!
mi = '0 0 -3';
ma = '0 0 -3';
break;
vector traceorigin = entcs_receiver(player_localentnum - 1).origin + (eZ * getstati(STAT_VIEWHEIGHT));
- vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+ vecs = decompressShotOrigin(STAT(SHOTORG));
traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
trueaimpoint = trace_endpos;
{
// accumulate damage with each stat update
static float damage_total_prev = 0;
- float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+ float damage_total = STAT(DAMAGE_DEALT_TOTAL);
float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
damage_total_prev = damage_total;
static float damage_dealt_time_prev = 0;
- float damage_dealt_time = getstatf(STAT_HIT_TIME);
+ float damage_dealt_time = STAT(HIT_TIME);
if (damage_dealt_time != damage_dealt_time_prev)
{
unaccounted_damage += unaccounted_damage_new;
static float hitsound_time_prev = 0;
// HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
- float arc_hack = activeweapon == WEP_ARC.m_id && autocvar_cl_hitsound >= 2;
+ float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
{
if (autocvar_cl_hitsound && unaccounted_damage)
}
static float typehit_time_prev = 0;
- float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+ float typehit_time = STAT(TYPEHIT_TIME);
if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
{
sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
{
- e = get_weaponinfo(switchingweapon);
+ e = switchingweapon;
if(e)
{
if(autocvar_crosshair_per_weapon)
if(autocvar_crosshair_pickup)
{
- float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+ float stat_pickup_time = STAT(LAST_PICKUP);
if(pickup_crosshair_time < stat_pickup_time)
{
ring_scale = autocvar_crosshair_ring_size;
float weapon_clipload, weapon_clipsize;
- weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
- weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+ weapon_clipload = STAT(WEAPON_CLIPLOAD);
+ weapon_clipsize = STAT(WEAPON_CLIPSIZE);
float ok_ammo_charge, ok_ammo_chargepool;
- ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
- ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOL);
+ ok_ammo_charge = STAT(OK_AMMO_CHARGE);
+ ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
float vortex_charge, vortex_chargepool;
- vortex_charge = getstatf(STAT_VORTEX_CHARGE);
- vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+ vortex_charge = STAT(VORTEX_CHARGE);
+ vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
float arc_heat = STAT(ARC_HEAT);
// handle the values
- if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX.m_id && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+ if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
{
if (vortex_chargepool || use_vortex_chargepool) {
use_vortex_chargepool = 1;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring_nexgun.tga";
}
- else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER.m_id && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
+ else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
{
- ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
+ ring_value = bound(0, STAT(LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (activeweapon == WEP_HAGAR.m_id && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+ else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
{
- ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+ ring_value = bound(0, STAT(HAGAR_LOAD) / hagar_maxrockets, 1);
ring_alpha = autocvar_crosshair_ring_hagar_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
// Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
// if a new image for another weapon is added, add the code (and its respective file/value) here
- if ((activeweapon == WEP_RIFLE.m_id) && (weapon_clipsize == 80))
+ if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
ring_image = "gfx/crosshair_ring_rifle.tga";
else
ring_image = "gfx/crosshair_ring.tga";
}
- else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC.m_id )
+ else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
{
ring_value = arc_heat;
ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
rgb = MUTATOR_ARGV(0, vector);
a = MUTATOR_ARGV(0, float);
}
- else if(getstati(STAT_FROZEN))
+ else if(STAT(FROZEN))
{
- rgb = ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+ rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
}
drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
if(!intermission)
- if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+ if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
- else if(getstatf(STAT_REVIVE_PROGRESS))
+ else if(STAT(REVIVE_PROGRESS))
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
++framecount;
stats_get();
- hud = getstati(STAT_HUD);
+ hud = STAT(HUD);
if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
vh_notice_time = time + autocvar_cl_vehicles_notify_time;
current_player = player_localentnum - 1;
else // then player_localentnum is the vehicle I'm driving
current_player = player_localnum;
- myteam = GetPlayerColor(current_player);
+ myteam = entcs_GetTeam(current_player);
if(myteam != prev_myteam)
{
prev_myteam = myteam;
}
- ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
float is_dead = (getstati(STAT_HEALTH) <= 0);
if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
{
float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
- float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+ float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
entity gen = world;
if(ons_roundlost)
ColorTranslateMode = autocvar_cl_stripcolorcodes;
// currently switching-to weapon (for crosshair)
- switchingweapon = getstati(STAT_SWITCHINGWEAPON);
+ switchingweapon = Weapons_from(STAT(SWITCHINGWEAPON));
// actually active weapon (for zoom)
- activeweapon = getstati(STAT_ACTIVEWEAPON);
+ activeweapon = Weapons_from(getstati(STAT_ACTIVEWEAPON));
+
+ switchweapon = Weapons_from(STAT(SWITCHWEAPON));
f = (serverflags & SERVERFLAG_TEAMPLAY);
if(f != teamplay)
{
last_activeweapon = activeweapon;
- e = get_weaponinfo(activeweapon);
+ e = activeweapon;
if(e.netname != "")
localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
else
if(autocvar_cl_reticle)
{
- Weapon wep = get_weaponinfo(activeweapon);
+ Weapon wep = activeweapon;
// Draw the aiming reticle for weapons that use it
// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
// It must be a persisted float for fading out to work properly (you let go of the zoom button for
}
}
- if(autocvar_hud_damage && !getstati(STAT_FROZEN))
+ if(autocvar_hud_damage && !STAT(FROZEN))
{
splash_size.x = max(vid_conwidth, vid_conheight);
splash_size.y = max(vid_conwidth, vid_conheight);
self.traileffect = 0;
switch (self.cnt)
{
- #define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
- CASE(ELECTRO) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(ROCKET) self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
- CASE(CRYLINK) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
- CASE(CRYLINK_BOUNCING) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
- CASE(ELECTRO_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(GRENADE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(GRENADE_BOUNCING) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(MINE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(BLASTER) self.traileffect = EFFECT_Null.m_id; break;
- CASE(HLAC) self.traileffect = EFFECT_Null.m_id; break;
- CASE(PORTO_RED) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
- CASE(PORTO_BLUE) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
- CASE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
- CASE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
- CASE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
- CASE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
- CASE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
- CASE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
- CASE(FLAC) self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
- CASE(SEEKER) self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
-
- CASE(MAGE_SPIKE) self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
- CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
- CASE(RAPTORBOMB) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
- CASE(RAPTORBOMBLET) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
- CASE(RAPTORCANNON) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
-
- CASE(SPIDERROCKET) self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
- CASE(WAKIROCKET) self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
- CASE(WAKICANNON) self.traileffect = EFFECT_Null.m_id; break;
-
- CASE(BUMBLE_GUN) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(BUMBLE_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
- CASE(RPC) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
-
- CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
-#undef CASE
+ #define HANDLE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
+ HANDLE(ELECTRO) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(ROCKET) self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
+ HANDLE(CRYLINK) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ HANDLE(CRYLINK_BOUNCING) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ HANDLE(ELECTRO_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(GRENADE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(GRENADE_BOUNCING) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(MINE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(BLASTER) self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(HLAC) self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(PORTO_RED) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ HANDLE(PORTO_BLUE) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ HANDLE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
+ HANDLE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ HANDLE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ HANDLE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
+ HANDLE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
+ HANDLE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+ HANDLE(FLAC) self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
+ HANDLE(SEEKER) self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
+
+ HANDLE(MAGE_SPIKE) self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
+ HANDLE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ HANDLE(RAPTORBOMB) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(RAPTORBOMBLET) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(RAPTORCANNON) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+
+ HANDLE(SPIDERROCKET) self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
+ HANDLE(WAKIROCKET) self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
+ HANDLE(WAKICANNON) self.traileffect = EFFECT_Null.m_id; break;
+
+ HANDLE(BUMBLE_GUN) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(BUMBLE_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ HANDLE(RPC) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+
+ HANDLE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
+#undef HANDLE
default:
if (MUTATOR_CALLHOOK(Ent_Projectile, self))
break;
--- /dev/null
+#include "anim.qh"
+
+/**
+ * @param anim x = startframe, y = numframes, z = framerate
+ */
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart)
+{
+ if (!anim) return; // no animation was given to us! We can't use this.
+
+ if (anim.x == e.animstate_startframe)
+ {
+ if (anim.y == e.animstate_numframes)
+ {
+ if (anim.z == e.animstate_framerate)
+ {
+ if (!restart) return;
+ if (anim.y == 1) // ZYM animation
+ BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
+ }
+ }
+ }
+ e.animstate_startframe = anim.x;
+ e.animstate_numframes = anim.y;
+ e.animstate_framerate = anim.z;
+ e.animstate_starttime = time - 0.1 * frametime; // shift it a little bit into the past to prevent float inaccuracy hiccups
+ e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
+ e.animstate_looping = looping;
+ e.animstate_override = override;
+ e.frame = e.animstate_startframe;
+ e.frame1time = time;
+}
+
+/**
+ * Update e.frame based on its animstate relative to time
+ */
+void anim_update(entity e)
+{
+ if (time >= e.animstate_endtime)
+ {
+ if (e.animstate_looping)
+ {
+ e.animstate_starttime = e.animstate_endtime;
+ e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
+ }
+ e.animstate_override = false;
+ }
+ float frameofs = bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
+ e.frame = e.animstate_startframe + frameofs;
+}
--- /dev/null
+#ifndef ANIM_H
+#define ANIM_H
+
+// begin engine fields
+
+/** primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) */
+.float frame;
+/** secondary framegroup animation (strength = lerpfrac) */
+.float frame2;
+/** tertiary framegroup animation (strength = lerpfrac3) */
+.float frame3;
+/** quaternary framegroup animation (strength = lerpfrac4) */
+.float frame4;
+
+/** strength of framegroup blend */
+.float lerpfrac;
+/** strength of framegroup blend */
+.float lerpfrac3;
+/** strength of framegroup blend */
+.float lerpfrac4;
+
+/** start time of framegroup animation */
+.float frame1time;
+/** start time of framegroup animation */
+.float frame2time;
+/** start time of framegroup animation */
+.float frame3time;
+/** start time of framegroup animation */
+.float frame4time;
+
+// end engine fields
+
+// player animation state
+
+.int animstate_startframe;
+.int animstate_numframes;
+.float animstate_framerate;
+.float animstate_starttime;
+.float animstate_endtime;
+/** whether to repeat */
+.bool animstate_looping;
+/** true for one cycle, then changed to false */
+.bool animstate_override;
+
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart);
+#define setanim(...) anim_set(__VA_ARGS__)
+void anim_update(entity e);
+#define updateanim(...) anim_update(__VA_ARGS__)
+
+#endif
ATTRIB(genericcommand_##id, m_description, string, description); \
ENDCLASS(genericcommand_##id) \
REGISTER(GENERIC_COMMANDS, CMD_G, id, m_id, NEW(genericcommand_##id)); \
- METHOD(genericcommand_##id, m_invokecmd, void(int request, int arguments, string command))
+ METHOD(genericcommand_##id, m_invokecmd, void(int request, entity caller, int arguments, string command))
STATIC_INIT(GENERIC_COMMANDS_aliases) {
FOREACH(GENERIC_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_svmenu"))));
CLASS(Command, Object)
ATTRIB(Command, m_name, string, string_null);
ATTRIB(Command, m_description, string, string_null);
- METHOD(Command, m_invokecmd, void(int request, int arguments, string command)) { }
+ METHOD(Command, m_invokecmd, void(int request, entity caller, int arguments, string command)) { }
ENDCLASS(Command)
#endif
{
string c = strtolower(argv(0));
FOREACH(GENERIC_COMMANDS, it.m_name == c, LAMBDA(
- it.m_invokecmd(CMD_REQUEST_COMMAND, argc, command);
+ it.m_invokecmd(CMD_REQUEST_COMMAND, NULL, argc, command);
return true;
));
return false;
{
string c = strtolower(argv(1));
FOREACH(GENERIC_COMMANDS, it.m_name == c, LAMBDA(
- it.m_invokecmd(CMD_REQUEST_USAGE, argc, "");
+ it.m_invokecmd(CMD_REQUEST_USAGE, NULL, argc, "");
return true;
));
return false;
// not so constant
-#ifdef SVQC
-#define PL_VIEW_OFS autocvar_sv_player_viewoffset
-#define PL_MIN autocvar_sv_player_mins
-#define PL_MAX autocvar_sv_player_maxs
-#define PL_CROUCH_VIEW_OFS autocvar_sv_player_crouch_viewoffset
-#define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
-#define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
-#define PL_HEAD autocvar_sv_player_headsize
-#elif defined(CSQC)
-#define PL_VIEW_OFS vec3(getstatf(STAT_PL_VIEW_OFS1), getstatf(STAT_PL_VIEW_OFS2), getstatf(STAT_PL_VIEW_OFS3))
-#define PL_MIN vec3(getstatf(STAT_PL_MIN1), getstatf(STAT_PL_MIN2), getstatf(STAT_PL_MIN3))
-#define PL_MAX vec3(getstatf(STAT_PL_MAX1), getstatf(STAT_PL_MAX2), getstatf(STAT_PL_MAX3))
-#define PL_CROUCH_VIEW_OFS vec3(getstatf(STAT_PL_CROUCH_VIEW_OFS1), getstatf(STAT_PL_CROUCH_VIEW_OFS2), getstatf(STAT_PL_CROUCH_VIEW_OFS3))
-#define PL_CROUCH_MIN vec3(getstatf(STAT_PL_CROUCH_MIN1), getstatf(STAT_PL_CROUCH_MIN2), getstatf(STAT_PL_CROUCH_MIN3))
-#define PL_CROUCH_MAX vec3(getstatf(STAT_PL_CROUCH_MAX1), getstatf(STAT_PL_CROUCH_MAX2), getstatf(STAT_PL_CROUCH_MAX3))
-#endif
+#define PL_VIEW_OFS STAT(PL_VIEW_OFS, NULL)
+#define PL_CROUCH_VIEW_OFS STAT(PL_CROUCH_VIEW_OFS, NULL)
+#define PL_MIN STAT(PL_MIN, NULL)
+#define PL_CROUCH_MIN STAT(PL_CROUCH_MIN, NULL)
+#define PL_MAX STAT(PL_MAX, NULL)
+#define PL_CROUCH_MAX STAT(PL_CROUCH_MAX, NULL)
// a bit more constant
const vector PL_MAX_CONST = '16 16 45';
# define TAG_VIEWLOC_NAME tag_networkviewloc
# define TAG_VIEWLOC_TYPE int
.float tag_networkviewloc;
+
+# define MOVETYPE_NAME move_movetype
#else
# define TAG_ENTITY_NAME tag_entity
# define TAG_ENTITY_TYPE entity
# define TAG_VIEWLOC_NAME viewloc
# define TAG_VIEWLOC_TYPE entity
+
+# define MOVETYPE_NAME movetype
#endif
// new fields
CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
- CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count)
+ CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count) \
+ CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, MOVETYPE_NAME)
// TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
// add hook function calls here
#define DEATH_ISVEHICLE(t) (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "vehicle")
#define DEATH_ISTURRET(t) (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "turret")
#define DEATH_ISMONSTER(t) (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "monster")
-#define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? WEP_Null : get_weaponinfo((t) & DEATH_WEAPONMASK))
+#define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? WEP_Null : Weapons_from((t) & DEATH_WEAPONMASK))
#define DEATH_ISWEAPON(t, w) (DEATH_WEAPONOF(t) == (w))
string Deathtype_Name(int deathtype);
bool autocvar_debugdraw;
#ifdef CSQC
+ string autocvar_debugdraw_filter;
.int debugdraw_last;
vector project_3d_to_2d(vector vec);
void Debug_Draw()
if (e.debugdraw_last == debugdraw_frame) continue;
e.debugdraw_last = debugdraw_frame;
vector rgb = (e.debug) ? '0 0 1' : '1 0 0';
+ if (autocvar_debugdraw_filter != "" && !strhasword(autocvar_debugdraw_filter, e.classname)) continue;
if (is_pure(e))
{
if (autocvar_debugdraw < 2) continue;
#endif
#ifdef SVQC
- GENERIC_COMMAND(debugdraw_sv, "Dump all server entities")
+ COMMON_COMMAND(debugdraw_sv, "Dump all server entities")
{
switch (request)
{
}
#endif
+GENERIC_COMMAND(bufstr_get, "Examine a string buffer object")
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ int bufhandle = stof(argv(1));
+ int string_index = stof(argv(2));
+ string s = bufstr_get(bufhandle, string_index);
+ LOG_INFOF("%s\n", s);
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " bufstr_get bufhandle string_index"));
+ return;
+ }
+ }
+}
+
#endif
*/
void globalsound(int channel, entity from, entity gs, float r, int chan, float vol, float atten)
{
+ assert(IS_PLAYER(from), eprint(from));
if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
WriteHeader(channel, globalsound);
WriteByte(channel, gs.m_id);
WriteByte(channel, r * 255);
WriteByte(channel, etof(from));
- WriteByte(channel, fabs(chan));
+ WriteByte(channel, chan);
WriteByte(channel, floor(vol * 255));
WriteByte(channel, floor(atten * 64));
entcs_force_origin(from);
*/
void playersound(int channel, entity from, entity ps, float r, int chan, float vol, float atten)
{
+ assert(IS_PLAYER(from), eprint(from));
if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
WriteHeader(channel, playersound);
WriteByte(channel, ps.m_id);
WriteByte(channel, r * 255);
WriteByte(channel, etof(from));
- WriteByte(channel, fabs(chan));
+ WriteByte(channel, chan);
WriteByte(channel, floor(vol * 255));
WriteByte(channel, floor(atten * 64));
entcs_force_origin(from);
string sample = GlobalSound_sample(gs.m_globalsoundstr, r);
int who = ReadByte();
entity e = entcs_receiver(who - 1);
- int chan = ReadByte();
+ int chan = ReadSByte();
float vol = ReadByte() / 255;
float atten = ReadByte() / 64;
vector o;
}
else
{
- entity e = new(globalsound);
- e.origin = o;
+ // Can this happen?
+ LOG_WARNINGF("Missing entcs data for player %d\n", who);
sound8(e, o, chan, sample, vol, atten, 0, 0);
- remove(e); // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
}
return true;
}
UpdatePlayerSounds(e);
string s = e.(ps.m_playersoundfld);
string sample = GlobalSound_sample(s, r);
- int chan = ReadByte();
+ int chan = ReadSByte();
float vol = ReadByte() / 255;
float atten = ReadByte() / 64;
vector o;
}
else
{
- LOG_WARNINGF("Missing entcs data for player %d\n", who);
// Can this happen?
- entity e = new(playersound);
- e.origin = o;
+ LOG_WARNINGF("Missing entcs data for player %d\n", who);
sound8(e, o, chan, sample, vol, atten, 0, 0);
- remove(e); // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
}
return true;
}
#ifdef SVQC
- void _GlobalSound(entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
+ bool autocvar_g_debug_globalsounds;
+
+ void _GlobalSound(entity this, entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
{
- SELFPARAM();
if (gs == NULL && ps == NULL && sample == "") return;
float r = random();
if (sample != "") sample = GlobalSound_sample(sample, r);
}
else
{
- if (gs) globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+ if (gs)
+ {
+ if(autocvar_g_debug_globalsounds)
+ globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+ else
+ _sound(this, chan, GlobalSound_sample(gs.m_globalsoundstr, r), VOL_BASE, ATTEN_NORM);
+ }
else if (ps) playersound(MSG_ALL, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
else _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
}
#ifdef SVQC
- void _GlobalSound(entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
- #define GlobalSound(def, chan, voicetype) _GlobalSound(def, NULL, string_null, chan, voicetype, false)
- #define GlobalSound_string(def, chan, voicetype) _GlobalSound(NULL, NULL, def, chan, voicetype, false)
- #define PlayerSound(def, chan, voicetype) _GlobalSound(NULL, def, string_null, chan, voicetype, false)
- #define VoiceMessage(def, msg) \
+ void _GlobalSound(entity this, entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
+ #define GlobalSound(this, def, chan, voicetype) _GlobalSound(this, def, NULL, string_null, chan, voicetype, false)
+ #define GlobalSound_string(this, def, chan, voicetype) _GlobalSound(this, NULL, NULL, def, chan, voicetype, false)
+ #define PlayerSound(thise, def, chan, voicetype) _GlobalSound(this, NULL, def, string_null, chan, voicetype, false)
+ #define VoiceMessage(this, def, msg) \
do \
{ \
entity VM = def; \
if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; \
else if (flood > 0) fake = false; \
else break; \
- _GlobalSound(NULL, VM, string_null, CH_VOICE, voicetype, fake); \
+ _GlobalSound(this, NULL, VM, string_null, CH_VOICE, voicetype, fake); \
} \
while (0)
// #define PROP(public, fld, sv, cl)
#define ENTCS_NETPROPS(PROP) \
PROP(true, sv_entnum, \
- { WriteByte(MSG_ENTITY, etof(player) - 1); }, \
+ { WriteByte(chan, etof(player) - 1); }, \
{ this.sv_entnum = ReadByte(); }) \
\
PROP(false, origin, \
- { WriteShort(MSG_ENTITY, this.origin.x); WriteShort(MSG_ENTITY, this.origin.y); \
- WriteShort(MSG_ENTITY, this.origin.z); }, \
+ { WriteShort(chan, this.origin.x); WriteShort(chan, this.origin.y); \
+ WriteShort(chan, this.origin.z); }, \
{ this.has_sv_origin = true; vector v; v.x = ReadShort(); v.y = ReadShort(); v.z = ReadShort(); setorigin(this, v); }) \
\
PROP(false, angles_y, \
- { WriteByte(MSG_ENTITY, this.angles.y / 360 * 256); }, \
+ { WriteByte(chan, this.angles.y / 360 * 256); }, \
{ vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; this.angles = v; }) \
\
PROP(false, health, \
- { WriteByte(MSG_ENTITY, this.health / 10); /* FIXME: use a better scale? */ }, \
+ { WriteByte(chan, this.health / 10); /* FIXME: use a better scale? */ }, \
{ this.healthvalue = ReadByte() * 10; }) \
\
PROP(false, armorvalue, \
- { WriteByte(MSG_ENTITY, this.armorvalue / 10); /* FIXME: use a better scale? */ }, \
+ { WriteByte(chan, this.armorvalue / 10); /* FIXME: use a better scale? */ }, \
{ this.armorvalue = ReadByte() * 10; }) \
\
PROP(true, netname, \
- { WriteString(MSG_ENTITY, this.netname); }, \
+ { WriteString(chan, this.netname); }, \
{ if (this.netname) strunzone(this.netname); this.netname = strzone(ReadString()); }) \
\
PROP(true, model, \
- { WriteString(MSG_ENTITY, this.model); }, \
+ { WriteString(chan, this.model); }, \
{ if (this.model) strunzone(this.model); this.model = strzone(ReadString()); }) \
\
PROP(true, skin, \
- { WriteByte(MSG_ENTITY, this.skin); }, \
+ { WriteByte(chan, this.skin); }, \
{ this.skin = ReadByte(); }) \
\
/**/
if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded ENTCS_NETPROPS limit");
}
- bool entcs_send(entity this, entity to, int sf)
+ bool _entcs_send(entity this, entity to, int sf, int chan)
{
entity player = this.owner;
sf |= BIT(0) | BIT(1);
this.m_forceupdate = 0;
bool valid =
IS_PLAYER(player) // player must be active
- && player.deadflag == DEAD_NO // player must be alive
|| player == to // player is self
;
if (!valid) sf = 0;
- WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
- WriteShort(MSG_ENTITY, sf);
+ if (chan == MSG_ENTITY)
+ WriteHeader(chan, ENT_CLIENT_ENTCS);
+ else
+ WriteHeader(chan, CLIENT_ENTCS);
+ WriteByte(chan, etof(player) - 1);
+ WriteShort(chan, sf);
int i = 1;
#define X(public, fld, sv, cl) { if (sf & BIT(i)) sv; } i += 1;
ENTCS_NETPROPS(X);
return true;
}
+ bool entcs_send(entity this, entity to, int sf)
+ {
+ return _entcs_send(this, to, sf, MSG_ENTITY);
+ }
+
void entcs_think()
{
SELFPARAM();
e.think = entcs_think;
e.nextthink = time;
Net_LinkEntity(e, false, 0, entcs_send);
+ if (!IS_REAL_CLIENT(player)) return;
+ FOR_EACH_CLIENT(e)
+ {
+ assert(e.entcs);
+ _entcs_send(e.entcs, msg_entity = player, BITS(23), MSG_ONE);
+ }
}
void entcs_detach(entity player)
void Ent_RemoveEntCS()
{
SELFPARAM();
- entcs_receiver(this.sv_entnum, NULL);
+ int n = this.sv_entnum;
+ entity e = entcs_receiver(n);
+ entcs_receiver(n, NULL);
+ if (e != this) remove(e);
}
void entcs_think()
{
SELFPARAM();
- this.nextthink = time;
entity e = CSQCModel_server2csqc(this.sv_entnum);
- bool exists = e != NULL;
- if (exists)
+ if (e == NULL)
{
- this.has_origin = true;
- this.origin = e.origin;
- // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
- if (this.model != e.model)
- {
- if (this.model) strunzone(this.model);
- this.model = strzone(e.model);
- }
+ this.has_origin = this.has_sv_origin;
+ return;
}
- else
+ this.has_origin = true;
+ this.origin = e.origin;
+ // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
+ if (this.model != e.model)
{
- this.has_origin = this.has_sv_origin;
+ if (this.model) strunzone(this.model);
+ this.model = strzone(e.model);
}
}
- NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+ bool ReadEntcs(entity this)
{
- if (isnew)
+ int n = ReadByte();
+ entity e = entcs_receiver(n);
+ if (e == NULL)
{
- make_pure(this);
- this.classname = "entcs_receiver";
- this.entremove = Ent_RemoveEntCS;
- this.think = entcs_think;
- this.nextthink = time;
+ if (this)
+ {
+ e = this;
+ }
+ else
+ {
+ e = new(entcs_receiver);
+ make_pure(e);
+ }
+ e.sv_entnum = n;
+ e.think = entcs_think;
+ entcs_receiver(n, e);
+ }
+ else if (this && e != this)
+ {
+ this.classname = "entcs_gc";
+ this.sv_entnum = n;
}
+ this = e;
InterpolateOrigin_Undo(this);
+ this.sv_entnum = n;
int sf = ReadShort();
this.has_sv_origin = false;
this.m_entcs_private = boolean(sf & BIT(0));
#define X(public, fld, sv, cl) { if (sf & BIT(i)) cl; } i += 1;
ENTCS_NETPROPS(X);
#undef X
- entcs_receiver(this.sv_entnum, this);
this.iflags |= IFLAG_ORIGIN;
InterpolateOrigin_Note(this);
+ WITH(entity, self, this, this.think());
return true;
}
+ NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+ {
+ if (isnew)
+ {
+ make_pure(this);
+ this.classname = "entcs_receiver";
+ this.entremove = Ent_RemoveEntCS;
+ }
+ return ReadEntcs(this);
+ }
+
+ NET_HANDLE(CLIENT_ENTCS, bool isnew)
+ {
+ return ReadEntcs(NULL);
+ }
+
#endif
#define ENT_CS_H
REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
+REGISTER_NET_TEMP(CLIENT_ENTCS)
/** True when private information such as origin is available */
.bool m_entcs_private;
#ifdef CSQC
- AL_declare(_entcs);
+ ArrayList _entcs;
STATIC_INIT(_entcs)
{
- AL_init(_entcs, 255, NULL, e); // 255 is the engine limit on maxclients
+ AL_NEW(_entcs, 255, NULL, e); // 255 is the engine limit on maxclients
}
SHUTDOWN(_entcs)
{
- AL_delete(_entcs);
+ AL_DELETE(_entcs);
}
#define entcs_receiver(...) EVAL(OVERLOAD(entcs_receiver, __VA_ARGS__))
#define entcs_receiver_1(i) AL_gete(_entcs, i)
#define entcs_receiver_2(i, v) AL_sete(_entcs, i, v)
#define entcs_is_self(e) ((e).sv_entnum == player_localentnum - 1)
+ /**
+ * @param i zero indexed player
+ */
+ bool entcs_IsSpectating(int i)
+ {
+ bool unconnected = !playerslots[i].gotscores;
+ return unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
+ }
+
/**
* @param i zero indexed player
* @returns 0 if not teamplay
*/
- int GetPlayerColorForce(int i)
+ int entcs_GetTeamColor(int i)
{
return (!teamplay) ? 0 : stof(getplayerkeyvalue(i, "colors")) & 15;
}
* @param i zero indexed player
* @returns 0 if not teamplay | NUM_TEAM_##N | NUM_SPECTATOR
*/
- int GetPlayerColor(int i)
+ int entcs_GetTeam(int i)
{
- bool unconnected = !playerslots[i].gotscores;
- bool spec = unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
- return (spec) ? NUM_SPECTATOR : GetPlayerColorForce(i);
+ return entcs_IsSpectating(i) ? NUM_SPECTATOR : entcs_GetTeamColor(i);
}
/**
* @param i zero indexed player
*/
- string GetPlayerName(int i)
+ string entcs_GetName(int i)
{
return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
}
/**
* @param i zero indexed player
*/
- float getplayeralpha(int i)
+ float entcs_GetAlpha(int i)
{
entity e = CSQCModel_server2csqc(i);
return e ? e.alpha : 1;
/**
* @param i zero indexed player
*/
- vector getcsqcplayercolor(int i)
+ vector entcs_GetColor(int i)
{
entity e = CSQCModel_server2csqc(i);
return (!e || e.colormap <= 0)
/**
* @param i zero indexed player
*/
- bool getplayerisdead(int i)
+ bool entcs_IsDead(int i)
{
entity e = CSQCModel_server2csqc(i);
return e ? e.csqcmodel_isdead : false;
#ifdef IMPLEMENTATION
#ifdef SVQC
-.float metertime;
+.float metertime = _STAT(NB_METERSTART);
int autocvar_g_nexball_goalleadlimit;
#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
Weapon w = WEP_NEXBALL;
w.wr_resetplayer(w);
plyr.switchweapon = WEP_NEXBALL.m_id;
- W_SwitchWeapon(WEP_NEXBALL.m_id);
+ W_SwitchWeapon(WEP_NEXBALL);
setself(this);
}
Weapon w = WEP_NEXBALL;
w.wr_resetplayer(w);
self.switchweapon = self.(weaponentity).switchweapon;
- W_SwitchWeapon(self.switchweapon);
+ W_SwitchWeapon(Weapons_from(self.switchweapon));
self.(weaponentity).weapons = '0 0 0';
}
if(g_nexball_meter_period <= 0)
g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
- addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
// General settings
/*
.float teleport_antispam;
-.bool ons_roundlost;
+.bool ons_roundlost = _STAT(ROUNDLOST);
// waypoint sprites
.entity bot_basewaypoint; // generator waypointsprite
for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
{
// Find weapon
- if(self.weapons & WepSet_FromWeapon(i))
+ if(self.weapons & WepSet_FromWeapon(Weapons_from(i)))
if(++c>=4)
break;
}
g_onslaught = true;
ons_captureshield_force = autocvar_g_onslaught_shield_force;
- addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
-
InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
}
--- /dev/null
+#include "all.qh"
--- /dev/null
+#ifndef IMPULSES_ALL_H
+#define IMPULSES_ALL_H
+
+REGISTRY(IMPULSES, 255)
+REGISTER_REGISTRY(IMPULSES)
+REGISTRY_SORT(IMPULSES)
+STATIC_INIT(IMPULSES_renumber)
+{
+ FOREACH(IMPULSES, true, LAMBDA(it.m_id = i));
+}
+REGISTRY_CHECK(IMPULSES)
+
+.void(entity this) impulse_handle;
+
+#if defined(CSQC)
+#define IMPULSE_ALIAS(alias, id) localcmd("\nalias " #alias " \"" id "\"\n")
+#else
+#define IMPULSE_ALIAS(alias, id)
+#endif
+
+#define REGISTER_IMPULSE(id, n) _REGISTER_IMPULSE(IMP_##id, id, n)
+#define _REGISTER_IMPULSE(id, alias, n) \
+ REGISTER(IMPULSES, id, m_id, new(Impulse)) \
+ { \
+ make_pure(this); \
+ this.impulse = n; \
+ IMPULSE_ALIAS(alias, "impulse " #n); \
+ }
+
+#define LEGACY_IMPULSE(alias, id, new) \
+ STATIC_INIT(legacy_##alias) { IMPULSE_ALIAS(alias, new); } \
+ SHUTDOWN(legacy_##alias) { IMPULSE_ALIAS(alias, "impulse " #id); }
+
+#define X(slot, imp) \
+ REGISTER_IMPULSE(weapon_group_##slot, imp) \
+ LEGACY_IMPULSE(weapon_group_##slot, imp, "impulse " #imp)
+X(1, 1)
+X(2, 2)
+X(3, 3)
+X(4, 4)
+X(5, 5)
+X(6, 6)
+X(7, 7)
+X(8, 8)
+X(9, 9)
+X(0, 14)
+#undef X
+
+#define X(slot, dir, imp) \
+ REGISTER_IMPULSE(weapon_priority_##slot##_##dir, imp) \
+ LEGACY_IMPULSE(weapon_priority_##slot##_##dir, imp, "impulse " #imp)
+X(0, prev, 200)
+X(1, prev, 201)
+X(2, prev, 202)
+X(3, prev, 203)
+X(4, prev, 204)
+X(5, prev, 205)
+X(6, prev, 206)
+X(7, prev, 207)
+X(8, prev, 208)
+X(9, prev, 209)
+
+X(0, best, 210)
+X(1, best, 211)
+X(2, best, 212)
+X(3, best, 213)
+X(4, best, 214)
+X(5, best, 215)
+X(6, best, 216)
+X(7, best, 217)
+X(8, best, 218)
+X(9, best, 219)
+
+X(0, next, 220)
+X(1, next, 221)
+X(2, next, 222)
+X(3, next, 223)
+X(4, next, 224)
+X(5, next, 225)
+X(6, next, 226)
+X(7, next, 227)
+X(8, next, 228)
+X(9, next, 229)
+#undef X
+
+// direct weapons
+
+#define X(i, imp) \
+ REGISTER_IMPULSE(weapon_byid_##i, imp)
+X(0, 230)
+X(1, 231)
+X(2, 232)
+X(3, 233)
+X(4, 234)
+X(5, 235)
+X(6, 236)
+X(7, 237)
+X(8, 238)
+X(9, 239)
+X(10, 240)
+X(11, 241)
+X(12, 242)
+X(13, 243)
+X(14, 244)
+X(15, 245)
+X(16, 246)
+X(17, 247)
+X(18, 248)
+X(19, 249)
+X(20, 250)
+X(21, 251)
+X(22, 252)
+X(23, 253)
+#undef X
+
+REGISTER_IMPULSE(weapon_next_byid, 10)
+LEGACY_IMPULSE(_weapnext_2, 10, "weapon_next_byid")
+
+REGISTER_IMPULSE(weapon_prev_byid, 12)
+LEGACY_IMPULSE(_weapprev_2, 12, "weapon_prev_byid")
+
+REGISTER_IMPULSE(weapon_next_bygroup, 18)
+LEGACY_IMPULSE(_weapnext_0, 18, "weapon_next_bygroup")
+
+REGISTER_IMPULSE(weapon_prev_bygroup, 19)
+LEGACY_IMPULSE(_weapprev_0, 19, "weapon_prev_bygroup")
+
+REGISTER_IMPULSE(weapon_next_bypriority, 15)
+LEGACY_IMPULSE(_weapnext_1, 15, "weapon_next_bypriority")
+
+REGISTER_IMPULSE(weapon_prev_bypriority, 16)
+LEGACY_IMPULSE(_weapprev_1, 16, "weapon_prev_bypriority")
+
+REGISTER_IMPULSE(weapon_last, 11)
+LEGACY_IMPULSE(weaplast, 11, "weapon_last")
+
+REGISTER_IMPULSE(weapon_best, 13)
+LEGACY_IMPULSE(weapbest, 13, "weapon_best")
+
+REGISTER_IMPULSE(weapon_drop, 17)
+LEGACY_IMPULSE(dropweapon, 17, "weapon_drop")
+
+REGISTER_IMPULSE(weapon_reload, 20)
+LEGACY_IMPULSE(reload, 20, "weapon_reload")
+
+REGISTER_IMPULSE(use, 21)
+LEGACY_IMPULSE(use, 21, "use")
+
+REGISTER_IMPULSE(waypoint_personal_here, 30)
+LEGACY_IMPULSE(g_waypointsprite_personal, 30, "waypoint_personal_here")
+
+REGISTER_IMPULSE(waypoint_personal_crosshair, 31)
+LEGACY_IMPULSE(g_waypointsprite_personal_p, 31, "waypoint_personal_crosshair")
+
+REGISTER_IMPULSE(waypoint_personal_death, 32)
+LEGACY_IMPULSE(g_waypointsprite_personal_d, 32, "waypoint_personal_death")
+
+REGISTER_IMPULSE(waypoint_here_follow, 33)
+LEGACY_IMPULSE(g_waypointsprite_team_helpme, 33, "waypoint_here_follow")
+
+REGISTER_IMPULSE(waypoint_here_here, 34)
+LEGACY_IMPULSE(g_waypointsprite_team_here, 34, "waypoint_here_here")
+
+REGISTER_IMPULSE(waypoint_here_crosshair, 35)
+LEGACY_IMPULSE(g_waypointsprite_team_here_p, 35, "waypoint_here_crosshair")
+
+REGISTER_IMPULSE(waypoint_here_death, 36)
+LEGACY_IMPULSE(g_waypointsprite_team_here_d, 36, "waypoint_here_death")
+
+REGISTER_IMPULSE(waypoint_danger_here, 37)
+LEGACY_IMPULSE(g_waypointsprite_team_danger, 37, "waypoint_danger_here")
+
+REGISTER_IMPULSE(waypoint_danger_crosshair, 38)
+LEGACY_IMPULSE(g_waypointsprite_team_danger_p, 38, "waypoint_danger_crosshair")
+
+REGISTER_IMPULSE(waypoint_danger_death, 39)
+LEGACY_IMPULSE(g_waypointsprite_team_danger_d, 39, "waypoint_danger_death")
+
+REGISTER_IMPULSE(waypoint_clear_personal, 47)
+LEGACY_IMPULSE(g_waypointsprite_clear_personal, 47, "waypoint_clear_personal")
+
+REGISTER_IMPULSE(waypoint_clear, 48)
+LEGACY_IMPULSE(g_waypointsprite_clear, 48, "waypoint_clear")
+
+REGISTER_IMPULSE(navwaypoint_spawn, 103)
+LEGACY_IMPULSE(g_waypointeditor_spawn, 103, "navwaypoint_spawn")
+
+REGISTER_IMPULSE(navwaypoint_remove, 104)
+LEGACY_IMPULSE(g_waypointeditor_remove, 104, "navwaypoint_remove")
+
+REGISTER_IMPULSE(navwaypoint_relink, 105)
+LEGACY_IMPULSE(g_waypointeditor_relinkall, 105, "navwaypoint_relink")
+
+REGISTER_IMPULSE(navwaypoint_save, 106)
+LEGACY_IMPULSE(g_waypointeditor_saveall, 106, "navwaypoint_save")
+
+REGISTER_IMPULSE(navwaypoint_unreachable, 107)
+LEGACY_IMPULSE(g_waypointeditor_unreachable, 107, "navwaypoint_unreachable")
+
+#define CHIMPULSE(id, n) _CHIMPULSE(CHIMPULSE_##id, n)
+#define _CHIMPULSE(id, n) \
+ REGISTER(IMPULSES, id, m_id, new(Impulse)) \
+ { \
+ make_pure(this); \
+ this.impulse = n; \
+ }
+
+CHIMPULSE(SPEEDRUN_INIT, 30)
+CHIMPULSE(GIVE_ALL, 99)
+CHIMPULSE(CLONE_MOVING, 140)
+CHIMPULSE(SPEEDRUN, 141)
+CHIMPULSE(CLONE_STANDING, 142)
+CHIMPULSE(TELEPORT, 143)
+CHIMPULSE(R00T, 148)
+
+#endif
minigame_read_owner();
float ent = ReadLong();
self.minigame_playerslot = ent;
- LOG_DEBUG("Player: ",GetPlayerName(ent-1),"\n");
+ LOG_DEBUG("Player: ",entcs_GetName(ent-1),"\n");
activate = (ent == player_localnum+1 && self.owner && self.owner != active_minigame);
entity prev = self;
for(int i = 0; i < maxclients; ++i)
{
- if ( player_localnum != i && playerslots[i] && GetPlayerName(i) != "" &&
+ if ( player_localnum != i && playerslots[i] && entcs_GetName(i) != "" &&
!findfloat(world,minigame_playerslot,i+1) && playerslots[i].ping )
{
e = HUD_MinigameMenu_SpawnSubEntry(
- strzone(GetPlayerName(i)), HUD_MinigameMenu_ClickInvite_Entry,
+ strzone(entcs_GetName(i)), HUD_MinigameMenu_ClickInvite_Entry,
self );
e.flags |= 1;
e.netname = strzone(ftos(i+1));
{
mypos = pos;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
mypos_y += player_fontsize_y;
return false;
}
-#endif
\ No newline at end of file
+#endif
FOREACH_MINIGAME_ENTITY(e)
if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & C4_TURN_TEAM) )
- playername = GetPlayerName(e.minigame_playerslot-1);
+ playername = entcs_GetName(e.minigame_playerslot-1);
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
if ( e.team == 2 )
mypos_y += player_fontsize_y + ts_y;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
mypos_y += player_fontsize_y;
FOREACH_MINIGAME_ENTITY(e)
if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & NMM_TURN_TEAM) )
- playername = GetPlayerName(e.minigame_playerslot-1);
+ playername = entcs_GetName(e.minigame_playerslot-1);
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
if ( e.team == 2 )
mypos_y += player_fontsize_y + ts_y;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
}
else if ( e.classname == "minigame_board_piece" )
drawfill(mypos, ts, pong_team_to_color(e.team), 0.25, DRAWFLAG_ADDITIVE);
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
+ (e.minigame_playerslot ? entcs_GetName(e.minigame_playerslot-1) : _("AI")),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(mypos+eY*player_fontsize_y,ftos(e.pong_score),'48 48 0',
FOREACH_MINIGAME_ENTITY(e)
if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & PP_TURN_TEAM) )
- playername = GetPlayerName(e.minigame_playerslot-1);
+ playername = entcs_GetName(e.minigame_playerslot-1);
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
if ( e.team == 2 )
mypos_y += player_fontsize_y + ts_y;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
mypos_y += player_fontsize_y;
{
mypos = pos;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
mypos_y += player_fontsize_y;
if ( e.team > 1 )
mypos_y += player_fontsize_y + (ts_y * (e.team - 1));
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
+ entcs_GetName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
vector tile_color = snake_teamcolor(e.team);
return false;
}
-#endif
\ No newline at end of file
+#endif
if ( e.team == 2 )
mypos_y += player_fontsize_y + ts_y;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
+ (e.minigame_playerslot ? entcs_GetName(e.minigame_playerslot-1) : _("AI")),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
mypos_y += player_fontsize_y;
return world;
}
-bool MinigameImpulse(int imp)
-{SELFPARAM();
- entity e = minigame_find_player(self);
- if ( imp && self.active_minigame && e )
+bool MinigameImpulse(entity this, int imp)
+{
+ if (!this.active_minigame) return false;
+ entity e = minigame_find_player(this);
+ if ( imp && this.active_minigame && e )
{
- return self.active_minigame.minigame_event(self.active_minigame,"impulse",e,imp);
+ return this.active_minigame.minigame_event(this.active_minigame,"impulse",e,imp);
}
return false;
}
bool minigame_CheckSend();
// Check for minigame impulses
-bool MinigameImpulse(int imp);
+bool MinigameImpulse(entity this, int imp);
// Parse a client command ( cmd minigame ... )
void ClientCommand_minigame(int request, int argc, string command);
if(delaytoo)
if(time < self.msound_delay)
return; // too early
- GlobalSound_string(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
+ GlobalSound_string(self, self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
self.msound_delay = time + sound_delay;
}
if(applygravity)
{
this.move_didgravity = 1;
- grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY;
+ grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
+ if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
this.move_velocity_z -= grav * 0.5;
else
this.move_velocity_z -= grav;
break;
push = this.move_velocity * time_left;
- vector prev_origin = this.move_origin;
_Movetype_PushEntity(this, push, true);
- if(trace_startsolid && this.move_origin != prev_origin)
+ if(trace_startsolid)
{
// we got teleported by a touch function
// let's abort the move
float my_trace_fraction = trace_fraction;
vector my_trace_plane_normal = trace_plane_normal;
- if(trace_plane_normal_z)
+ if(trace_plane_normal.z)
{
- if(trace_plane_normal_z > 0.7)
+ if(trace_plane_normal.z > 0.7)
{
// floor
blocked |= 1;
vector steppush = '0 0 1' * stepheight;
_Movetype_PushEntity(this, steppush, true);
- if(trace_startsolid && this.move_origin != org)
+ if(trace_startsolid)
{
blocked |= 8;
break;
}
_Movetype_PushEntity(this, push, true);
- if(trace_startsolid && this.move_origin != org)
+ if(trace_startsolid)
{
blocked |= 8;
break;
float trace2_fraction = trace_fraction;
steppush = '0 0 1' * (org_z - this.move_origin_z);
_Movetype_PushEntity(this, steppush, true);
- if(trace_startsolid && this.move_origin != org)
+ if(trace_startsolid)
{
blocked |= 8;
break;
{
if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
+ if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
this.move_velocity_z -= grav * 0.5f;
}
}
// this.move_velocity = '0 0 0';
}
-bool _Movetype_CheckWater(entity ent) // SV_CheckWater
+bool _Movetype_CheckWater(entity this) // SV_CheckWater
{
- vector point = ent.move_origin;
- point.z += (ent.mins.z + 1);
+ vector point = this.move_origin;
+ point.z += this.mins.z + 1;
int nativecontents = pointcontents(point);
- if(ent.move_watertype && ent.move_watertype != nativecontents)
+ if(this.move_watertype && this.move_watertype != nativecontents)
{
- // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
- if(ent.contentstransition)
- ent.contentstransition(ent.move_watertype, nativecontents);
+ // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", this.move_watertype, nativecontents);
+ if(this.contentstransition)
+ this.contentstransition(this.move_watertype, nativecontents);
}
- ent.move_waterlevel = 0;
- ent.move_watertype = CONTENT_EMPTY;
+ this.move_waterlevel = WATERLEVEL_NONE;
+ this.move_watertype = CONTENT_EMPTY;
int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
if(supercontents & DPCONTENTS_LIQUIDSMASK)
{
- ent.move_watertype = nativecontents;
- ent.move_waterlevel = 1;
- point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
+ this.move_watertype = nativecontents;
+ this.move_waterlevel = WATERLEVEL_WETFEET;
+ point.z = this.move_origin.z + (this.mins.z + this.maxs.z) * 0.5;
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
{
- ent.move_waterlevel = 2;
- point.y = ent.origin.y + ent.view_ofs.y;
+ this.move_waterlevel = WATERLEVEL_SWIMMING;
+ point.z = this.move_origin.z + this.view_ofs.z;
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
- ent.move_waterlevel = 3;
+ this.move_waterlevel = WATERLEVEL_SUBMERGED;
}
}
- return ent.move_waterlevel > 1;
+ return this.move_waterlevel > 1;
}
void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
for (entity e = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); e; e = e.chain)
{
+ if(e.move_nomonsters != MOVE_NOMONSTERS && e.move_nomonsters != MOVE_WORLDONLY)
if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
{
other = this;
trace_fraction = 1;
trace_inwater = false;
trace_inopen = true;
- trace_endpos = e.origin;
+ trace_endpos = e.move_origin;
trace_plane_normal = '0 0 1';
trace_plane_dist = 0;
trace_ent = this;
int cont = this.dphitcontentsmask;
this.dphitcontentsmask = DPCONTENTS_SOLID;
- tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, MOVE_NOMONSTERS, this);
+ tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
this.dphitcontentsmask = cont;
if(trace_startsolid)
if(!_Movetype_TestEntityPosition(this, '0 0 -1' * i)) goto success;
if(!_Movetype_TestEntityPosition(this, '0 0 1' * i)) goto success;
}
- LOG_TRACEF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
+ LOG_DEBUG("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
num_for_edict(this), this.classname, vtos(this.move_origin));
return false;
: success;
- LOG_TRACEF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
+ LOG_DEBUG("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
num_for_edict(this), this.classname, vtos(this.move_origin));
_Movetype_LinkEdict(this, true);
return true;
type = max(0, this.move_nomonsters);
else if(this.move_movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
+ else if(this.move_movetype == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
else if(this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
type = MOVE_NOMONSTERS;
else
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
_Movetype_Physics_Toss(this, movedt);
break;
+ case MOVETYPE_PHYSICS:
+ break;
+ }
+}
+
+void _Movetype_Physics_ClientFrame(entity this, float movedt)
+{
+ this.move_didgravity = -1;
+ switch (this.move_movetype)
+ {
+ case MOVETYPE_PUSH:
+ case MOVETYPE_FAKEPUSH:
+ _Movetype_Physics_Pusher(this, movedt);
+ break;
+ case MOVETYPE_NONE:
+ break;
+ case MOVETYPE_FOLLOW:
+ _Movetype_Physics_Follow(this);
+ break;
+ case MOVETYPE_NOCLIP:
+ _Movetype_CheckWater(this);
+ this.move_origin = this.move_origin + TICRATE * this.move_velocity;
+ this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+ _Movetype_LinkEdict(this, false);
+ break;
+ case MOVETYPE_STEP:
+ _Movetype_Physics_Step(this, movedt);
+ break;
+ case MOVETYPE_WALK:
+ case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
+ _Movetype_Physics_Walk(this, movedt);
+ break;
+ case MOVETYPE_TOSS:
+ case MOVETYPE_BOUNCE:
+ case MOVETYPE_BOUNCEMISSILE:
+ case MOVETYPE_FLYMISSILE:
+ _Movetype_Physics_Toss(this, movedt);
+ break;
+ case MOVETYPE_PHYSICS:
+ break;
}
}
if(this.move_didgravity > 0)
{
- this.velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
* (this.gravity ? this.gravity : 1)
- * PHYS_GRAVITY;
+ * PHYS_GRAVITY(this);
}
this.angles = this.move_angles + dt * this.avelocity;
setorigin(this, trace_endpos);
}
- if(this.move_didgravity > 0 && GRAVITY_UNAFFECTED_BY_TICRATE)
- this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+ if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
}
else
{
// should match sv_gameplayfix_fixedcheckwatertransition
float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
-#ifdef SVQC
-.int stat_gameplayfix_upvelocityclearsonground;
-
-#define GRAVITY_UNAFFECTED_BY_TICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
-#define UPWARD_VELOCITY_CLEARS_ONGROUND autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag
-
-#define TICRATE sys_frametime
-#elif defined(CSQC)
-#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
-#define UPWARD_VELOCITY_CLEARS_ONGROUND getstati(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
-
-#define TICRATE ticrate
-#endif
-
.entity move_groundentity; // FIXME add move_groundnetworkentity?
.float move_suspendedinair;
.float move_didgravity;
const int MOVETYPE_BOUNCE = 10;
const int MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing
const int MOVETYPE_FOLLOW = 12;
+const int MOVETYPE_PHYSICS = 32;
const int MOVETYPE_FLY_WORLDONLY = 33;
const int FL_ITEM = 256;
const int MOVETYPE_FAKEPUSH = 13;
-const float MOVEFLAG_Q2AIRACCELERATE = 1;
-const float MOVEFLAG_NOGRAVITYONGROUND = 2;
-const float MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4;
+const int MOVEFLAG_VALID = BIT(23);
+const int MOVEFLAG_Q2AIRACCELERATE = BIT(0);
+const int MOVEFLAG_NOGRAVITYONGROUND = BIT(1);
+const int MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = BIT(2);
#ifdef CSQC
-// TODO: figure out server's version of this
-#define moveflags (getstati(STAT_MOVEFLAGS))
+#define moveflags STAT(MOVEFLAGS)
#endif
#endif
{
if (this.move_flags & FL_ONGROUND)
{
- if (this.move_velocity.z >= 1 / 32)
+ if (this.move_velocity.z >= 1 / 32 && UPWARD_VELOCITY_CLEARS_ONGROUND)
{
this.move_flags &= ~FL_ONGROUND;
}
if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
{
this.move_didgravity = 1;
- this.move_velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ this.move_velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
* (this.gravity ? this.gravity : 1)
- * PHYS_GRAVITY;
+ * PHYS_GRAVITY(this);
}
this.move_angles = this.move_angles + this.move_avelocity * dt;
{
float bouncefac = this.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
float bouncestop = this.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
- bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+ bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1 + bouncefac);
break;
}
- if (GRAVITY_UNAFFECTED_BY_TICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
- this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
+ this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
_Movetype_CheckWaterTransition(this);
}
// move up
vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
- vector prev_origin = this.move_origin;
_Movetype_PushEntity(this, upmove, true);
if(wasfreed(this))
return;
- if(trace_startsolid && this.move_origin != prev_origin)
+ if(trace_startsolid)
{
// we got teleported when upstepping... must abort the move
return;
// move down
vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
- vector prev_origin = this.move_origin;
_Movetype_PushEntity(this, downmove, true);
if(wasfreed(this))
return;
- if(trace_startsolid && this.move_origin != prev_origin)
+ if(trace_startsolid)
{
// we got teleported when downstepping... must abort the move
return;
REGISTRY(Mutators, BITS(7))
#define Mutators_from(i) _Mutators_from(i, NULL)
Mutator loaded_mutators[Mutators_MAX];
+bool Mutator_Add(Mutator mut);
+void Mutator_Remove(Mutator mut);
+bool mutator_log = false;
+
+#ifndef MENUQC
+REGISTER_NET_LINKED(Mutator)
+
+#ifdef SVQC
+bool Mutator_SendEntity(entity this, entity to, int sf)
+{
+ int chan = MSG_ENTITY;
+ WriteHeader(chan, Mutator);
+ WriteString(chan, this.registered_id);
+ return true;
+}
+#endif
+
+#ifdef CSQC
+void NET_Mutator_Remove()
+{
+ SELFPARAM();
+ string s = this.netname;
+ WITH(bool, mutator_log, true, LAMBDA(
+ FOREACH(Mutators, it.registered_id == s, LAMBDA(Mutator_Remove(it)));
+ ));
+}
+NET_HANDLE(Mutator, bool isNew)
+{
+ string s = this.netname = ReadString();
+ return = true;
+ if (isNew)
+ {
+ make_pure(this);
+ this.entremove = NET_Mutator_Remove;
+ int added = 0;
+ WITH(bool, mutator_log, true, LAMBDA(
+ FOREACH(Mutators, it.registered_id == s, LAMBDA(Mutator_Add(it); ++added));
+ ));
+ if (added > 1) LOG_WARNINGF("Added more than one mutator for %s\n", s);
+ }
+}
+#endif
+
+#endif
bool Mutator_Add(Mutator mut)
{
mutatorfunc_t func = mut.mutatorfunc;
if (!func(MUTATOR_ADDING)) {
// good
+ if (mutator_log) LOG_TRACEF("Mutator: added %s\n", mut.m_name);
+#ifdef SVQC
+ Net_LinkEntity(mut, false, 0, Mutator_SendEntity);
+#endif
return true;
}
backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
// baaaaad
error("Mutator_Remove: removing mutator failed");
}
+ if (mutator_log) LOG_TRACEF("Mutator: removed %s\n", mut.m_name);
+#ifdef SVQC
+ Net_UnlinkEntity(mut);
+#endif
}
#define REGISTER_MUTATOR(id, dependence) \
float pm_maxspeed_mod;
MUTATOR_HOOKABLE(PM_Physics, EV_PM_Physics);
+/** called when a weapon model is about to be set, allows custom paths etc. */
+#define EV_WeaponModel(i, o) \
+ /**/ i(string, weapon_model) \
+ /**/ i(string, weapon_model_output) \
+ /**/ o(string, weapon_model_output) \
+ /**/
+string weapon_model;
+string weapon_model_output;
+MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
+
#endif
ENDCLASS(Buff)
#ifdef SVQC
- .int buffs;
+ // .int buffs = _STAT(BUFFS);
void buff_Init(entity ent);
void buff_Init_Compat(entity ent, entity replacement);
#define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
#include "../../../triggers/target/music.qh"
#include "../../../gamemodes/all.qh"
-.float buff_time;
+.float buff_time = _STAT(BUFF_TIME);
void buffs_DelayedInit();
REGISTER_MUTATOR(buffs, cvar("g_buffs"))
{
MUTATOR_ONADD
{
- addstat(STAT_BUFFS, AS_INT, buffs);
- addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
-
InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET);
}
}
REGISTER_MUTATOR(cl_buffs, true);
MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
{
- int allBuffs = getstati(STAT_BUFFS, 0, 24);
+ int allBuffs = STAT(BUFFS);
FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
- addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
+ addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
));
}
MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
#if defined(SVQC)
void bugrigs_SetVars();
-void bugrigs_AddStats();
REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
{
MUTATOR_ONADD
{
bugrigs_SetVars();
- bugrigs_AddStats();
}
return false;
}
#endif
-#ifdef CSQC
-
-#define PHYS_BUGRIGS getstati(STAT_BUGRIGS)
-#define PHYS_BUGRIGS_ANGLE_SMOOTHING getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
-#define PHYS_BUGRIGS_PLANAR_MOVEMENT getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
-#define PHYS_BUGRIGS_REVERSE_SPEEDING getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
-#define PHYS_BUGRIGS_FRICTION_FLOOR getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
-#define PHYS_BUGRIGS_AIR_STEERING getstati(STAT_BUGRIGS_AIR_STEERING)
-#define PHYS_BUGRIGS_FRICTION_BRAKE getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
-#define PHYS_BUGRIGS_ACCEL getstatf(STAT_BUGRIGS_ACCEL)
-#define PHYS_BUGRIGS_SPEED_REF getstatf(STAT_BUGRIGS_SPEED_REF)
-#define PHYS_BUGRIGS_SPEED_POW getstatf(STAT_BUGRIGS_SPEED_POW)
-#define PHYS_BUGRIGS_STEER getstatf(STAT_BUGRIGS_STEER)
-#define PHYS_BUGRIGS_FRICTION_AIR getstatf(STAT_BUGRIGS_FRICTION_AIR)
-#define PHYS_BUGRIGS_CAR_JUMPING getstatf(STAT_BUGRIGS_CAR_JUMPING)
-#define PHYS_BUGRIGS_REVERSE_SPINNING getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
-#define PHYS_BUGRIGS_REVERSE_STOPPING getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
-
-#elif defined(SVQC)
-
-bool g_bugrigs;
-bool g_bugrigs_planar_movement;
-bool g_bugrigs_planar_movement_car_jumping;
-float g_bugrigs_reverse_spinning;
-float g_bugrigs_reverse_speeding;
-float g_bugrigs_reverse_stopping;
-float g_bugrigs_air_steering;
-float g_bugrigs_angle_smoothing;
-float g_bugrigs_friction_floor;
-float g_bugrigs_friction_brake;
-float g_bugrigs_friction_air;
-float g_bugrigs_accel;
-float g_bugrigs_speed_ref;
-float g_bugrigs_speed_pow;
-float g_bugrigs_steer;
-
-#define PHYS_BUGRIGS g_bugrigs
-#define PHYS_BUGRIGS_ANGLE_SMOOTHING g_bugrigs_angle_smoothing
-#define PHYS_BUGRIGS_PLANAR_MOVEMENT g_bugrigs_planar_movement
-#define PHYS_BUGRIGS_REVERSE_SPEEDING g_bugrigs_reverse_speeding
-#define PHYS_BUGRIGS_FRICTION_FLOOR g_bugrigs_friction_floor
-#define PHYS_BUGRIGS_AIR_STEERING g_bugrigs_air_steering
-#define PHYS_BUGRIGS_FRICTION_BRAKE g_bugrigs_friction_brake
-#define PHYS_BUGRIGS_ACCEL g_bugrigs_accel
-#define PHYS_BUGRIGS_SPEED_REF g_bugrigs_speed_ref
-#define PHYS_BUGRIGS_SPEED_POW g_bugrigs_speed_pow
-#define PHYS_BUGRIGS_STEER g_bugrigs_steer
-#define PHYS_BUGRIGS_FRICTION_AIR g_bugrigs_friction_air
-#define PHYS_BUGRIGS_CAR_JUMPING g_bugrigs_planar_movement_car_jumping
-#define PHYS_BUGRIGS_REVERSE_SPINNING g_bugrigs_reverse_spinning
-#define PHYS_BUGRIGS_REVERSE_STOPPING g_bugrigs_reverse_stopping
-
-.float stat_bugrigs;
-.float stat_bugrigs_angle_smoothing;
-.float stat_bugrigs_planar_movement;
-.float stat_bugrigs_reverse_speeding;
-.float stat_bugrigs_friction_floor;
-.float stat_bugrigs_air_steering;
-.float stat_bugrigs_friction_brake;
-.float stat_bugrigs_accel;
-.float stat_bugrigs_speed_ref;
-.float stat_bugrigs_speed_pow;
-.float stat_bugrigs_steer;
-.float stat_bugrigs_friction_air;
-.float stat_bugrigs_car_jumping;
-.float stat_bugrigs_reverse_spinning;
-.float stat_bugrigs_reverse_stopping;
+#define PHYS_BUGRIGS(s) STAT(BUGRIGS, s)
+#define PHYS_BUGRIGS_ACCEL(s) STAT(BUGRIGS_ACCEL, s)
+#define PHYS_BUGRIGS_AIR_STEERING(s) STAT(BUGRIGS_AIR_STEERING, s)
+#define PHYS_BUGRIGS_ANGLE_SMOOTHING(s) STAT(BUGRIGS_ANGLE_SMOOTHING, s)
+#define PHYS_BUGRIGS_CAR_JUMPING(s) STAT(BUGRIGS_CAR_JUMPING, s)
+#define PHYS_BUGRIGS_FRICTION_AIR(s) STAT(BUGRIGS_FRICTION_AIR, s)
+#define PHYS_BUGRIGS_FRICTION_BRAKE(s) STAT(BUGRIGS_FRICTION_BRAKE, s)
+#define PHYS_BUGRIGS_FRICTION_FLOOR(s) STAT(BUGRIGS_FRICTION_FLOOR, s)
+#define PHYS_BUGRIGS_PLANAR_MOVEMENT(s) STAT(BUGRIGS_PLANAR_MOVEMENT, s)
+#define PHYS_BUGRIGS_REVERSE_SPEEDING(s) STAT(BUGRIGS_REVERSE_SPEEDING, s)
+#define PHYS_BUGRIGS_REVERSE_SPINNING(s) STAT(BUGRIGS_REVERSE_SPINNING, s)
+#define PHYS_BUGRIGS_REVERSE_STOPPING(s) STAT(BUGRIGS_REVERSE_STOPPING, s)
+#define PHYS_BUGRIGS_SPEED_POW(s) STAT(BUGRIGS_SPEED_POW, s)
+#define PHYS_BUGRIGS_SPEED_REF(s) STAT(BUGRIGS_SPEED_REF, s)
+#define PHYS_BUGRIGS_STEER(s) STAT(BUGRIGS_STEER, s)
+
+#if defined(SVQC)
void bugrigs_SetVars()
{
g_bugrigs_steer = cvar("g_bugrigs_steer");
}
-void bugrigs_UpdateStats(entity this)
-{
- this.stat_bugrigs = PHYS_BUGRIGS;
- this.stat_bugrigs_angle_smoothing = PHYS_BUGRIGS_ANGLE_SMOOTHING;
- this.stat_bugrigs_planar_movement = PHYS_BUGRIGS_PLANAR_MOVEMENT;
- this.stat_bugrigs_reverse_speeding = PHYS_BUGRIGS_REVERSE_SPEEDING;
- this.stat_bugrigs_friction_floor = PHYS_BUGRIGS_FRICTION_FLOOR;
- this.stat_bugrigs_air_steering = PHYS_BUGRIGS_AIR_STEERING;
- this.stat_bugrigs_friction_brake = PHYS_BUGRIGS_FRICTION_BRAKE;
- this.stat_bugrigs_accel = PHYS_BUGRIGS_ACCEL;
- this.stat_bugrigs_speed_ref = PHYS_BUGRIGS_SPEED_REF;
- this.stat_bugrigs_speed_pow = PHYS_BUGRIGS_SPEED_POW;
- this.stat_bugrigs_steer = PHYS_BUGRIGS_STEER;
- this.stat_bugrigs_friction_air = PHYS_BUGRIGS_FRICTION_AIR;
- this.stat_bugrigs_car_jumping = PHYS_BUGRIGS_CAR_JUMPING;
- this.stat_bugrigs_reverse_spinning = PHYS_BUGRIGS_REVERSE_SPINNING;
- this.stat_bugrigs_reverse_stopping = PHYS_BUGRIGS_REVERSE_STOPPING;
-}
-
-void bugrigs_AddStats()
-{
- addstat(STAT_BUGRIGS, AS_INT, stat_bugrigs);
- addstat(STAT_BUGRIGS_ANGLE_SMOOTHING, AS_INT, stat_bugrigs_angle_smoothing);
- addstat(STAT_BUGRIGS_PLANAR_MOVEMENT, AS_INT, stat_bugrigs_planar_movement);
- addstat(STAT_BUGRIGS_REVERSE_SPEEDING, AS_INT, stat_bugrigs_reverse_speeding);
- addstat(STAT_BUGRIGS_FRICTION_FLOOR, AS_FLOAT, stat_bugrigs_friction_floor);
- addstat(STAT_BUGRIGS_AIR_STEERING, AS_INT, stat_bugrigs_air_steering);
- addstat(STAT_BUGRIGS_FRICTION_BRAKE, AS_FLOAT, stat_bugrigs_friction_brake);
- addstat(STAT_BUGRIGS_ACCEL, AS_FLOAT, stat_bugrigs_accel);
- addstat(STAT_BUGRIGS_SPEED_REF, AS_FLOAT, stat_bugrigs_speed_ref);
- addstat(STAT_BUGRIGS_SPEED_POW, AS_FLOAT, stat_bugrigs_speed_pow);
- addstat(STAT_BUGRIGS_STEER, AS_FLOAT, stat_bugrigs_steer);
- addstat(STAT_BUGRIGS_FRICTION_AIR, AS_FLOAT, stat_bugrigs_friction_air);
- addstat(STAT_BUGRIGS_CAR_JUMPING, AS_FLOAT, stat_bugrigs_car_jumping);
- addstat(STAT_BUGRIGS_REVERSE_SPINNING, AS_FLOAT, stat_bugrigs_reverse_spinning);
- addstat(STAT_BUGRIGS_REVERSE_STOPPING, AS_FLOAT, stat_bugrigs_reverse_stopping);
-}
-
#endif
void RaceCarPhysics(entity this)
float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
- if (PHYS_BUGRIGS_REVERSE_SPEEDING)
+ if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
{
if (accel < 0)
{
this.angles_z = 0;
makevectors(this.angles); // new forward direction!
- if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING)
+ if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
{
float myspeed = this.velocity * v_forward;
float upspeed = this.velocity * v_up;
// responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF, PHYS_BUGRIGS_SPEED_POW));
- //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF) ^ PHYS_BUGRIGS_SPEED_POW);
+ float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this), PHYS_BUGRIGS_SPEED_POW(this)));
+ //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
float steerfactor;
- if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING)
- steerfactor = -myspeed * PHYS_BUGRIGS_STEER;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
+ steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
else
- steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER;
+ steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
float accelfactor;
- if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING)
- accelfactor = PHYS_BUGRIGS_ACCEL;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ accelfactor = PHYS_BUGRIGS_ACCEL(this);
else
- accelfactor = f * PHYS_BUGRIGS_ACCEL;
- //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL;
+ accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
+ //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
if (accel < 0)
{
if (myspeed > 0)
{
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR - PHYS_BUGRIGS_FRICTION_BRAKE * accel));
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
}
else
{
- if (!PHYS_BUGRIGS_REVERSE_SPEEDING)
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
+ if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
}
}
else
{
if (myspeed >= 0)
{
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
}
else
{
- if (PHYS_BUGRIGS_REVERSE_STOPPING)
+ if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
myspeed = 0;
else
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR + PHYS_BUGRIGS_FRICTION_BRAKE * accel));
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
}
}
// terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
- //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR;
+ //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
makevectors(this.angles); // new forward direction!
float myspeed = vlen(this.velocity);
// responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF), PHYS_BUGRIGS_SPEED_POW));
+ float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
float steerfactor = -myspeed * f;
this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
makevectors(this.angles); // new forward direction!
}
- rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR * PHYS_INPUT_TIMELENGTH);
- //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR;
+ rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
+ //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
//MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
//MAXIMA: solve(total_acceleration(v) = 0, v);
- if (PHYS_BUGRIGS_PLANAR_MOVEMENT)
+ if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
{
vector rigvel_xy, neworigin, up;
float mt;
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
rigvel_xy = vec2(rigvel);
- if (PHYS_BUGRIGS_CAR_JUMPING)
+ if (PHYS_BUGRIGS_CAR_JUMPING(this))
mt = MOVE_NORMAL;
else
mt = MOVE_NOMONSTERS;
}
else
{
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
this.velocity = rigvel;
this.movetype = MOVETYPE_FLY;
}
// smooth the angles
vector vf1, vu1, smoothangles;
makevectors(this.angles);
- float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING, 1);
+ float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
if (f == 0)
f = 1;
vf1 = v_forward * f;
#endif
MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
{
- if(!PHYS_BUGRIGS || !IS_PLAYER(self)) { return false; }
+ if(!PHYS_BUGRIGS(self) || !IS_PLAYER(self)) { return false; }
#ifdef SVQC
self.angles = self.bugrigs_prevangles;
MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
{
- if(!PHYS_BUGRIGS) { return false; }
+ if(!PHYS_BUGRIGS(self)) { return false; }
#ifdef SVQC
self.bugrigs_prevangles = self.angles;
-
- bugrigs_UpdateStats(self);
#endif
return false;
}
#ifdef IMPLEMENTATION
+#define PHYS_DODGING STAT(DODGING, this)
+#define PHYS_DODGING_DELAY STAT(DODGING_DELAY, this)
+#define PHYS_DODGING_DISTANCE_THRESHOLD STAT(DODGING_DISTANCE_THRESHOLD, this)
+#define PHYS_DODGING_FROZEN_NODOUBLETAP STAT(DODGING_FROZEN_NO_DOUBLETAP, this)
+#define PHYS_DODGING_HEIGHT_THRESHOLD STAT(DODGING_HEIGHT_THRESHOLD, this)
+#define PHYS_DODGING_HORIZ_SPEED STAT(DODGING_HORIZ_SPEED, this)
+#define PHYS_DODGING_HORIZ_SPEED_FROZEN STAT(DODGING_HORIZ_SPEED_FROZEN, this)
+#define PHYS_DODGING_RAMP_TIME STAT(DODGING_RAMP_TIME, this)
+#define PHYS_DODGING_UP_SPEED STAT(DODGING_UP_SPEED, this)
+#define PHYS_DODGING_WALL STAT(DODGING_WALL, this)
+#define PHYS_DODGING_PRESSED_KEYS(s) (s).pressedkeys
+
#ifdef CSQC
#define PHYS_DODGING_FRAMETIME (1 / (frametime <= 0 ? 60 : frametime))
- #define PHYS_DODGING getstati(STAT_DODGING)
- #define PHYS_DODGING_DELAY getstatf(STAT_DODGING_DELAY)
- #define PHYS_DODGING_TIMEOUT(s) getstatf(STAT_DODGING_TIMEOUT)
- #define PHYS_DODGING_HORIZ_SPEED_FROZEN getstatf(STAT_DODGING_HORIZ_SPEED_FROZEN)
- #define PHYS_DODGING_FROZEN_NODOUBLETAP getstati(STAT_DODGING_FROZEN_NO_DOUBLETAP)
- #define PHYS_DODGING_HORIZ_SPEED getstatf(STAT_DODGING_HORIZ_SPEED)
- #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys
- #define PHYS_DODGING_HEIGHT_THRESHOLD getstatf(STAT_DODGING_HEIGHT_THRESHOLD)
- #define PHYS_DODGING_DISTANCE_THRESHOLD getstatf(STAT_DODGING_DISTANCE_THRESHOLD)
- #define PHYS_DODGING_RAMP_TIME getstatf(STAT_DODGING_RAMP_TIME)
- #define PHYS_DODGING_UP_SPEED getstatf(STAT_DODGING_UP_SPEED)
- #define PHYS_DODGING_WALL getstatf(STAT_DODGING_WALL)
+ #define PHYS_DODGING_TIMEOUT(s) STAT(DODGING_TIMEOUT)
#elif defined(SVQC)
#define PHYS_DODGING_FRAMETIME sys_frametime
- #define PHYS_DODGING g_dodging
- #define PHYS_DODGING_DELAY autocvar_sv_dodging_delay
#define PHYS_DODGING_TIMEOUT(s) s.cvar_cl_dodging_timeout
- #define PHYS_DODGING_HORIZ_SPEED_FROZEN autocvar_sv_dodging_horiz_speed_frozen
- #define PHYS_DODGING_FROZEN_NODOUBLETAP autocvar_sv_dodging_frozen_doubletap
- #define PHYS_DODGING_HORIZ_SPEED autocvar_sv_dodging_horiz_speed
- #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys
- #define PHYS_DODGING_HEIGHT_THRESHOLD autocvar_sv_dodging_height_threshold
- #define PHYS_DODGING_DISTANCE_THRESHOLD autocvar_sv_dodging_wall_distance_threshold
- #define PHYS_DODGING_RAMP_TIME autocvar_sv_dodging_ramp_time
- #define PHYS_DODGING_UP_SPEED autocvar_sv_dodging_up_speed
- #define PHYS_DODGING_WALL autocvar_sv_dodging_wall_dodging
-
- float autocvar_sv_dodging_delay;
- float autocvar_sv_dodging_height_threshold;
- float autocvar_sv_dodging_horiz_speed;
- float autocvar_sv_dodging_horiz_speed_frozen;
- float autocvar_sv_dodging_ramp_time;
- bool autocvar_sv_dodging_sound;
- float autocvar_sv_dodging_up_speed;
- float autocvar_sv_dodging_wall_distance_threshold;
- bool autocvar_sv_dodging_wall_dodging;
- bool autocvar_sv_dodging_frozen_doubletap;
+
+
#endif
#ifdef SVQC
-float g_dodging;
+bool autocvar_sv_dodging_sound;
// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
.float dodging_action;
#include "../../../animdecide.qh"
#include "../../../physics.qh"
-.float cvar_cl_dodging_timeout;
-
-.float stat_dodging;
-.float stat_dodging_delay;
-.float stat_dodging_horiz_speed_frozen;
-.float stat_dodging_frozen_nodoubletap;
-.float stat_dodging_frozen;
-.float stat_dodging_horiz_speed;
-.float stat_dodging_height_threshold;
-.float stat_dodging_distance_threshold;
-.float stat_dodging_ramp_time;
-.float stat_dodging_up_speed;
-.float stat_dodging_wall;
+.float cvar_cl_dodging_timeout = _STAT(DODGING_TIMEOUT);
REGISTER_MUTATOR(dodging, cvar("g_dodging"))
{
MUTATOR_ONADD
{
g_dodging = cvar("g_dodging");
- addstat(STAT_DODGING, AS_INT, stat_dodging);
- addstat(STAT_DODGING_DELAY, AS_FLOAT, stat_dodging_delay);
- addstat(STAT_DODGING_TIMEOUT, AS_FLOAT, cvar_cl_dodging_timeout); // we stat this, so it is updated on the client when updated on server (otherwise, chaos)
- addstat(STAT_DODGING_FROZEN_NO_DOUBLETAP, AS_INT, stat_dodging_frozen_nodoubletap);
- addstat(STAT_DODGING_HORIZ_SPEED_FROZEN, AS_FLOAT, stat_dodging_horiz_speed_frozen);
- addstat(STAT_DODGING_FROZEN, AS_INT, stat_dodging_frozen);
- addstat(STAT_DODGING_HORIZ_SPEED, AS_FLOAT, stat_dodging_horiz_speed);
- addstat(STAT_DODGING_HEIGHT_THRESHOLD, AS_FLOAT, stat_dodging_height_threshold);
- addstat(STAT_DODGING_DISTANCE_THRESHOLD, AS_FLOAT, stat_dodging_distance_threshold);
- addstat(STAT_DODGING_RAMP_TIME, AS_FLOAT, stat_dodging_ramp_time);
- addstat(STAT_DODGING_UP_SPEED, AS_FLOAT, stat_dodging_up_speed);
- addstat(STAT_DODGING_WALL, AS_FLOAT, stat_dodging_wall);
}
// this just turns off the cvar.
.int pressedkeys;
#endif
-void dodging_UpdateStats(entity this)
-{
-#ifdef SVQC
- this.stat_dodging = PHYS_DODGING;
- this.stat_dodging_delay = PHYS_DODGING_DELAY;
- this.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
- this.stat_dodging_frozen = PHYS_DODGING_FROZEN;
- this.stat_dodging_frozen_nodoubletap = PHYS_DODGING_FROZEN_NODOUBLETAP;
- this.stat_dodging_height_threshold = PHYS_DODGING_HEIGHT_THRESHOLD;
- this.stat_dodging_distance_threshold = PHYS_DODGING_DISTANCE_THRESHOLD;
- this.stat_dodging_ramp_time = PHYS_DODGING_RAMP_TIME;
- this.stat_dodging_up_speed = PHYS_DODGING_UP_SPEED;
- this.stat_dodging_wall = PHYS_DODGING_WALL;
-#endif
-}
-
// returns 1 if the player is close to a wall
bool check_close_to_wall(entity this, float threshold)
{
if (!PHYS_DODGING)
return;
- dodging_UpdateStats(this);
-
if (PHYS_DEAD(this))
return;
#ifdef SVQC
if (autocvar_sv_dodging_sound)
- PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ PlayerSound(this, playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
animdecide_setaction(this, ANIMACTION_JUMP, true);
#endif
#endif
#include "../../../physics.qh"
-
-#if defined(SVQC)
-void doublejump_AddStats();
-
-REGISTER_MUTATOR(doublejump, true)
-{
- MUTATOR_ONADD
- {
- doublejump_AddStats();
- }
- return false;
-}
+#ifdef SVQC
+REGISTER_MUTATOR(doublejump, autocvar_sv_doublejump);
#elif defined(CSQC)
REGISTER_MUTATOR(doublejump, true);
#endif
-
-#ifdef CSQC
-
-#define PHYS_DOUBLEJUMP getstati(STAT_DOUBLEJUMP)
-
-#elif defined(SVQC)
-
-bool autocvar_sv_doublejump;
-
-#define PHYS_DOUBLEJUMP autocvar_sv_doublejump
-
-.int stat_doublejump;
-
-void doublejump_UpdateStats(entity this)
-{
- this.stat_doublejump = PHYS_DOUBLEJUMP;
-}
-
-void doublejump_AddStats()
-{
- addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
-}
-
-#endif
+#define PHYS_DOUBLEJUMP(s) STAT(DOUBLEJUMP, s)
MUTATOR_HOOKFUNCTION(doublejump, PlayerJump)
{
- if (PHYS_DOUBLEJUMP)
+ if (PHYS_DOUBLEJUMP(self))
{
tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
return false;
}
-MUTATOR_HOOKFUNCTION(doublejump, PlayerPhysics)
-{
-#ifdef SVQC
- doublejump_UpdateStats(self);
-#endif
- return false;
-}
-
-#ifdef SVQC
-
-MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsString)
-{
- ret_string = strcat(ret_string, ":doublejump");
- return false;
-}
-
-MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsPrettyString)
-{
- ret_string = strcat(ret_string, ", Double jump");
- return false;
-}
-
-#endif
#endif
#if defined(SVQC)
-void multijump_AddStats();
-
-REGISTER_MUTATOR(multijump, cvar("g_multijump"))
-{
- MUTATOR_ONADD
- {
- multijump_AddStats();
- }
- return false;
-}
+REGISTER_MUTATOR(multijump, cvar("g_multijump"));
#elif defined(CSQC)
REGISTER_MUTATOR(multijump, true);
#endif
-.int multijump_count;
+#define PHYS_MULTIJUMP STAT(MULTIJUMP, self)
+#define PHYS_MULTIJUMP_SPEED STAT(MULTIJUMP_SPEED, self)
+#define PHYS_MULTIJUMP_ADD STAT(MULTIJUMP_ADD, self)
+#define PHYS_MULTIJUMP_MAXSPEED STAT(MULTIJUMP_MAXSPEED, self)
+#define PHYS_MULTIJUMP_DODGING STAT(MULTIJUMP_DODGING, self)
+#define PHYS_MULTIJUMP_COUNT(s) STAT(MULTIJUMP_COUNT, s)
+
.bool multijump_ready;
#ifdef CSQC
+bool autocvar_cl_multijump = false;
-bool autocvar_cl_multijump = true;
-
-#define PHYS_MULTIJUMP getstati(STAT_MULTIJUMP)
-#define PHYS_MULTIJUMP_SPEED getstatf(STAT_MULTIJUMP_SPEED)
-#define PHYS_MULTIJUMP_ADD getstati(STAT_MULTIJUMP_ADD)
-#define PHYS_MULTIJUMP_MAXSPEED getstatf(STAT_MULTIJUMP_MAXSPEED)
-#define PHYS_MULTIJUMP_DODGING getstati(STAT_MULTIJUMP_DODGING)
-#define PHYS_MULTIJUMP_COUNT(s) getstati(STAT_MULTIJUMP_COUNT)
-#define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
-
+ #define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
#elif defined(SVQC)
-
.bool cvar_cl_multijump;
-int autocvar_g_multijump;
-float autocvar_g_multijump_add;
-float autocvar_g_multijump_speed;
-float autocvar_g_multijump_maxspeed;
-float autocvar_g_multijump_dodging = 1;
-
-#define PHYS_MULTIJUMP autocvar_g_multijump
-#define PHYS_MULTIJUMP_SPEED autocvar_g_multijump_speed
-#define PHYS_MULTIJUMP_ADD autocvar_g_multijump_add
-#define PHYS_MULTIJUMP_MAXSPEED autocvar_g_multijump_maxspeed
-#define PHYS_MULTIJUMP_DODGING autocvar_g_multijump_dodging
-#define PHYS_MULTIJUMP_COUNT(s) (s).multijump_count
-#define PHYS_MULTIJUMP_CLIENT(s) (s).cvar_cl_multijump
-
-.float stat_multijump;
-.float stat_multijump_speed;
-.float stat_multijump_add;
-.float stat_multijump_maxspeed;
-.float stat_multijump_dodging;
-
-void multijump_UpdateStats(entity this)
-{
- this.stat_multijump = PHYS_MULTIJUMP;
- this.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
- this.stat_multijump_add = PHYS_MULTIJUMP_ADD;
- this.stat_multijump_maxspeed = PHYS_MULTIJUMP_MAXSPEED;
- this.stat_multijump_dodging = PHYS_MULTIJUMP_DODGING;
-}
-
-void multijump_AddStats()
-{
- addstat(STAT_MULTIJUMP, AS_INT, stat_multijump);
- addstat(STAT_MULTIJUMP_SPEED, AS_FLOAT, stat_multijump_speed);
- addstat(STAT_MULTIJUMP_ADD, AS_INT, stat_multijump_add);
- addstat(STAT_MULTIJUMP_MAXSPEED, AS_FLOAT, stat_multijump_maxspeed);
- addstat(STAT_MULTIJUMP_DODGING, AS_INT, stat_multijump_dodging);
- addstat(STAT_MULTIJUMP_COUNT, AS_INT, multijump_count);
-}
-
+ #define PHYS_MULTIJUMP_CLIENT(s) (s).cvar_cl_multijump
#endif
-void PM_multijump(entity this)
-{
- if(!PHYS_MULTIJUMP) { return; }
-
- if(IS_ONGROUND(this))
- this.multijump_count = 0;
-}
-
bool PM_multijump_checkjump(entity this)
{
if(!PHYS_MULTIJUMP) { return false; }
MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
{
-#ifdef SVQC
- multijump_UpdateStats(self);
-#elif defined(CSQC)
+#ifdef CSQC
self.multijump_count = PHYS_MULTIJUMP_COUNT(self);
#endif
- PM_multijump(self);
+ if(!PHYS_MULTIJUMP) { return; }
+
+ if(IS_ONGROUND(self))
+ self.multijump_count = 0;
return false;
}
REGISTER_MUTATOR(cl_nades, true);
MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
{
- if (getstatf(STAT_HEALING_ORB) <= time) return false;
+ if (STAT(HEALING_ORB) <= time) return false;
MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
- MUTATOR_ARGV(0, float) = getstatf(STAT_HEALING_ORB_ALPHA);
+ MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
return true;
}
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
}
void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
{
- float bonusNades = getstatf(STAT_NADE_BONUS);
- float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
- float bonusType = getstati(STAT_NADE_BONUS_TYPE);
+ float bonusNades = STAT(NADE_BONUS);
+ float bonusProgress = STAT(NADE_BONUS_SCORE);
+ float bonusType = STAT(NADE_BONUS_TYPE);
Nade def = Nades_from(bonusType);
vector nadeColor = def.m_color;
string nadeIcon = def.m_icon;
#include "../../../monsters/sv_monsters.qh"
#include "../../../../server/g_subs.qh"
-REGISTER_MUTATOR(nades, cvar("g_nades"))
-{
- MUTATOR_ONADD
- {
- addstat(STAT_NADE_TIMER, AS_FLOAT, nade_timer);
- addstat(STAT_NADE_BONUS, AS_FLOAT, bonus_nades);
- addstat(STAT_NADE_BONUS_TYPE, AS_INT, nade_type);
- addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
- addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
- addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
- }
-
- return false;
-}
+REGISTER_MUTATOR(nades, cvar("g_nades"));
.float nade_time_primed;
.entity nade;
.entity fake_nade;
-.float nade_timer;
+.float nade_timer = _STAT(NADE_TIMER);
.float nade_refire;
-.float bonus_nades;
+.float bonus_nades = _STAT(NADE_BONUS);
.float nade_special_time;
-.float bonus_nade_score;
-.float nade_type;
+.float bonus_nade_score = _STAT(NADE_BONUS_SCORE);
+.int nade_type = _STAT(NADE_BONUS_TYPE);
.string pokenade_type;
.entity nade_damage_target;
.float cvar_cl_nade_type;
.string cvar_cl_pokenade_type;
.float toss_time;
-.float stat_healing_orb;
-.float stat_healing_orb_alpha;
+.float stat_healing_orb = _STAT(HEALING_ORB);
+.float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA);
.float nade_show_particles;
bool healer_send(entity this, entity to, int sf);
// mark the guns as ok to use by e.g. impulse 99
for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
if(nt_IsNewToy(i))
- get_weaponinfo(i).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+ Weapons_from(i).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
}
MUTATOR_ONROLLBACK_OR_REMOVE
{
for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
if(nt_IsNewToy(i))
- get_weaponinfo(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ Weapons_from(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
}
MUTATOR_ONREMOVE
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- entity e = get_weaponinfo(i);
+ entity e = Weapons_from(i);
if(!e.weapon)
continue;
for (j = 0; j < n; ++j)
for (k = WEP_FIRST; k <= WEP_LAST; ++k)
{
- Weapon w = get_weaponinfo(k);
+ Weapon w = Weapons_from(k);
if (w.netname == argv(j))
{
WepSet seti = e.m_wepset;
for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
if (NIX_CanChooseWeapon(i)) {
- Weapon w = get_weaponinfo(i);
+ Weapon w = Weapons_from(i);
w.wr_init(w);
}
}
e.ammo_rockets = start_ammo_rockets;
e.ammo_fuel = start_ammo_fuel;
e.weapons = start_weapons;
- if(!client_hasweapon(e, e.weapon, true, false))
+ if(!client_hasweapon(e, Weapons_from(e.weapon), true, false))
e.switchweapon = w_getbestweapon(self);
}
}
bool NIX_CanChooseWeapon(int wpn)
{
- entity e = get_weaponinfo(wpn);
+ entity e = Weapons_from(wpn);
if(!e.weapon) // skip dummies
return false;
if(g_weaponarena)
nix_nextchange = time; // start the first round now!
else
nix_nextchange = time + autocvar_g_balance_nix_roundtime;
- // Weapon w = get_weaponinfo(nix_weapon);
+ // Weapon w = Weapons_from(nix_weapon);
// w.wr_init(w); // forget it, too slow
}
// get weapon info
- entity e = get_weaponinfo(nix_weapon);
+ entity e = Weapons_from(nix_weapon);
if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
{
self.weapons |= e.m_wepset;
if(self.switchweapon != nix_weapon)
- if(!client_hasweapon(self, self.switchweapon, true, false))
- if(client_hasweapon(self, nix_weapon, true, false))
- W_SwitchWeapon(nix_weapon);
+ if(!client_hasweapon(self, Weapons_from(self.switchweapon), true, false))
+ {
+ Weapon w = Weapons_from(nix_weapon);
+ if(client_hasweapon(self, w, true, false))
+ W_SwitchWeapon(w);
+ }
}
MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
return;
}
- Weapon w = get_weaponinfo(actor.weapon);
- if(!w.wr_checkammo1(w))
+ if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(WEP_CVAR(hmg, reload_ammo) && actor.clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
{
if (fire & 1)
#ifdef SVQC
#include "overkill.qc"
#endif
+#ifdef CSQC
+ #ifdef IMPLEMENTATION
+ REGISTER_MUTATOR(ok, false)
+ {
+ MUTATOR_ONADD {
+ cvar_settemp("g_overkill", "1");
+ WEP_SHOTGUN.mdl = "ok_shotgun";
+ WEP_MACHINEGUN.mdl = "ok_mg";
+ WEP_VORTEX.mdl = "ok_sniper";
+ }
+ }
+ #endif
+#endif
.float ok_notice_time;
.float ammo_charge[Weapons_MAX];
-.float ok_use_ammocharge;
-.float ok_ammo_charge;
+.float ok_use_ammocharge = _STAT(OK_AMMO_CHARGE);
+.float ok_ammo_charge = _STAT(OK_AMMO_CHARGEPOOL);
.float ok_pauseregen_finished;
{
if(!ent.ok_use_ammocharge) return;
- entity wepent = get_weaponinfo(wep);
+ entity wepent = Weapons_from(wep);
if(wepent.weapon == 0)
return; // dummy
void ok_IncreaseCharge(entity ent, int wep)
{
- entity wepent = get_weaponinfo(wep);
+ entity wepent = Weapons_from(wep);
if(wepent.weapon == 0)
return; // dummy
{
if(!ent.ok_use_ammocharge) return true;
- entity wepent = get_weaponinfo(wep);
+ entity wepent = Weapons_from(wep);
if(wepent.weapon == 0)
return 0; // dummy
self.ok_notice_time = time + 2;
play2(self, SND(DRYFIRE));
}
- Weapon wpn = get_weaponinfo(self.weapon);
+ Weapon wpn = Weapons_from(self.weapon);
.entity weaponentity = weaponentities[0]; // TODO: unhardcode
if(self.(weaponentity).state != WS_CLEAR)
w_ready(wpn, self, weaponentity, (self.BUTTON_ATCK ? 1 : 0) | (self.BUTTON_ATCK2 ? 2 : 0));
precache_all_playermodels("models/ok_player/*.dpm");
- addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
- addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
-
WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(WEP_CVAR(rpc, reload_ammo) && actor.clip_load < WEP_CVAR(rpc, ammo)) {
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
{
if (fire & 1)
MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
{SELFPARAM();
for(int j = WEP_FIRST; j <= WEP_LAST; ++j)
- if(self.weapons & WepSet_FromWeapon(j))
+ if(self.weapons & WepSet_FromWeapon(Weapons_from(j)))
if(self.switchweapon != j)
if(W_IsWeaponThrowable(j))
W_ThrowNewWeapon(self, j, false, self.origin + (self.mins + self.maxs) * 0.5, randomvec() * 175 + '0 0 325');
int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
-REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate") && teamplay);
+REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
.entity msnt_lookat;
MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
{SELFPARAM();
+ if(!teamplay) { return false; }
// Note: when entering this, fixangle is already set.
if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
{
else
fixedmakevectors(team_mate.angles);
- for(pc = 0; pc != 5; ++pc) // test 5 diffrent spots close to mate
+ for(pc = 0; pc < 5; ++pc) // test 5 diffrent spots close to mate
{
switch(pc)
{
float spritelookupblinkvalue(string s)
{SELFPARAM();
if (s == WP_Weapon.netname) {
- if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
+ if (Weapons_from(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
return 2;
}
if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypointblink;
vector spritelookupcolor(entity this, string s, vector def)
{
- if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+ if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return Weapons_from(this.wp_extra).wpcolor;
if (s == WP_Item.netname || s == RADARICON_Item.netname) return Items_from(this.wp_extra).m_color;
if (MUTATOR_CALLHOOK(WP_Format, this, s))
{
string spritelookuptext(string s)
{SELFPARAM();
if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
- if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).m_name;
+ if (s == WP_Weapon.netname) return Weapons_from(self.wp_extra).m_name;
if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypoint;
if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
if (MUTATOR_CALLHOOK(WP_Format, this, s))
InterpolateOrigin_Do(self);
- float t = GetPlayerColor(player_localnum) + 1;
+ float t = entcs_GetTeam(player_localnum) + 1;
string spriteimage = "";
return cvar(strcat("sv_", option));
}
-void Physics_AddStats()
-{
- // static view offset and hitbox vectors
- // networked for all you bandwidth pigs out there
- addstat(STAT_PL_VIEW_OFS1, AS_FLOAT, stat_pl_view_ofs_x);
- addstat(STAT_PL_VIEW_OFS2, AS_FLOAT, stat_pl_view_ofs_y);
- addstat(STAT_PL_VIEW_OFS3, AS_FLOAT, stat_pl_view_ofs_z);
- addstat(STAT_PL_CROUCH_VIEW_OFS1, AS_FLOAT, stat_pl_crouch_view_ofs_x);
- addstat(STAT_PL_CROUCH_VIEW_OFS2, AS_FLOAT, stat_pl_crouch_view_ofs_y);
- addstat(STAT_PL_CROUCH_VIEW_OFS3, AS_FLOAT, stat_pl_crouch_view_ofs_z);
-
- addstat(STAT_PL_MIN1, AS_FLOAT, stat_pl_min_x);
- addstat(STAT_PL_MIN2, AS_FLOAT, stat_pl_min_y);
- addstat(STAT_PL_MIN3, AS_FLOAT, stat_pl_min_z);
- addstat(STAT_PL_MAX1, AS_FLOAT, stat_pl_max_x);
- addstat(STAT_PL_MAX2, AS_FLOAT, stat_pl_max_y);
- addstat(STAT_PL_MAX3, AS_FLOAT, stat_pl_max_z);
- addstat(STAT_PL_CROUCH_MIN1, AS_FLOAT, stat_pl_crouch_min_x);
- addstat(STAT_PL_CROUCH_MIN2, AS_FLOAT, stat_pl_crouch_min_y);
- addstat(STAT_PL_CROUCH_MIN3, AS_FLOAT, stat_pl_crouch_min_z);
- addstat(STAT_PL_CROUCH_MAX1, AS_FLOAT, stat_pl_crouch_max_x);
- addstat(STAT_PL_CROUCH_MAX2, AS_FLOAT, stat_pl_crouch_max_y);
- addstat(STAT_PL_CROUCH_MAX3, AS_FLOAT, stat_pl_crouch_max_z);
-
- // g_movementspeed hack
- addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
- addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
- addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
- addstat(STAT_MOVEVARS_HIGHSPEED, AS_FLOAT, stat_movement_highspeed);
-
- // jet pack
- addstat(STAT_JETPACK_ACCEL_SIDE, AS_FLOAT, stat_jetpack_accel_side);
- addstat(STAT_JETPACK_ACCEL_UP, AS_FLOAT, stat_jetpack_accel_up);
- addstat(STAT_JETPACK_ANTIGRAVITY, AS_FLOAT, stat_jetpack_antigravity);
- addstat(STAT_JETPACK_FUEL, AS_FLOAT, stat_jetpack_fuel);
- addstat(STAT_JETPACK_MAXSPEED_UP, AS_FLOAT, stat_jetpack_maxspeed_up);
- addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
-
- // hack to fix track_canjump
- addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
- addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
-
- // jump speed caps
- addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps);
-
- // hacks
- addstat(STAT_MOVEVARS_FRICTION_ONLAND, AS_FLOAT, stat_sv_friction_on_land);
- addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick);
- addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump);
-
- // new properties
- addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
- addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
- addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
- addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
- addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
- addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
- addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
- addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
- addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
- addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
- addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
- addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
- addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
- addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground);
-}
-
void Physics_UpdateStats(entity this, float maxspd_mod)
{
- // blah
- this.stat_pl_view_ofs = PL_VIEW_OFS;
- this.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
-
- this.stat_pl_min = PL_MIN;
- this.stat_pl_max = PL_MAX;
- this.stat_pl_crouch_min = PL_CROUCH_MIN;
- this.stat_pl_crouch_max = PL_CROUCH_MAX;
-
-
- this.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
- if(Physics_ClientOption(this, "airstrafeaccel_qw"))
- this.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod);
- else
- this.stat_sv_airstrafeaccel_qw = 0;
- this.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
- this.stat_sv_maxspeed = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
- this.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this!
-
- this.stat_jetpack_antigravity = PHYS_JETPACK_ANTIGRAVITY;
- this.stat_jetpack_accel_up = PHYS_JETPACK_ACCEL_UP;
- this.stat_jetpack_accel_side = PHYS_JETPACK_ACCEL_SIDE;
- this.stat_jetpack_maxspeed_side = PHYS_JETPACK_MAXSPEED_SIDE;
- this.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP;
- this.stat_jetpack_fuel = PHYS_JETPACK_FUEL;
-
- this.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS;
-
- this.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND;
- this.stat_sv_friction_slick = PHYS_FRICTION_SLICK;
-
- this.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP;
-
+ STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
+ STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw"))
+ ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod)
+ : 0;
+ STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
+ STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
// old stats
// fix some new settings
- this.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
- this.stat_sv_maxairstrafespeed = Physics_ClientOption(this, "maxairstrafespeed");
- this.stat_sv_maxairspeed = Physics_ClientOption(this, "maxairspeed");
- this.stat_sv_airstrafeaccelerate = Physics_ClientOption(this, "airstrafeaccelerate");
- this.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(this, "warsowbunny_turnaccel");
- this.stat_sv_airaccel_sideways_friction = Physics_ClientOption(this, "airaccel_sideways_friction");
- this.stat_sv_aircontrol = Physics_ClientOption(this, "aircontrol");
- this.stat_sv_aircontrol_power = Physics_ClientOption(this, "aircontrol_power");
- this.stat_sv_aircontrol_penalty = Physics_ClientOption(this, "aircontrol_penalty");
- this.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
- this.stat_sv_warsowbunny_topspeed = Physics_ClientOption(this, "warsowbunny_topspeed");
- this.stat_sv_warsowbunny_accel = Physics_ClientOption(this, "warsowbunny_accel");
- this.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(this, "warsowbunny_backtosideratio");
- this.stat_sv_friction = Physics_ClientOption(this, "friction");
- this.stat_sv_accelerate = Physics_ClientOption(this, "accelerate");
- this.stat_sv_stopspeed = Physics_ClientOption(this, "stopspeed");
- this.stat_sv_airaccelerate = Physics_ClientOption(this, "airaccelerate");
- this.stat_sv_airstopaccelerate = Physics_ClientOption(this, "airstopaccelerate");
- this.stat_sv_jumpvelocity = Physics_ClientOption(this, "jumpvelocity");
-
- this.stat_sv_track_canjump = Physics_ClientOption(this, "track_canjump");
-
- this.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
+ STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
+ STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed");
+ STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed");
+ STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate");
+ STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel");
+ STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction");
+ STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol");
+ STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power");
+ STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty");
+ STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
+ STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed");
+ STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel");
+ STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio");
+ STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction");
+ STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate");
+ STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed");
+ STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate");
+ STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate");
+ STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity");
+ STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump");
}
#endif
: a * pow(fabs(b / a), lerp);
}
-noref float pmove_waterjumptime;
-
#define unstick_offsets(X) \
/* 1 no nudge (just return the original if this test passes) */ \
X(' 0.000 0.000 0.000') \
void PM_ClientMovement_UpdateStatus(entity this, bool ground)
{
+#ifdef CSQC
// make sure player is not stuck
- PM_ClientMovement_Unstick(this);
+ if(autocvar_cl_movement != 3)
+ PM_ClientMovement_Unstick(this);
// set crouched
if (PHYS_INPUT_BUTTON_CROUCH(this))
vector origin1 = this.origin + '0 0 1';
vector origin2 = this.origin - '0 0 1';
- if (ground)
+ if (ground && autocvar_cl_movement != 3)
{
tracebox(origin1, this.mins, this.maxs, origin2, MOVE_NORMAL, this);
if (trace_fraction < 1.0 && trace_plane_normal.z > 0.7)
UNSET_ONGROUND(this);
}
- // set watertype/waterlevel
- origin1 = this.origin;
- origin1.z += this.mins_z + 1;
- this.waterlevel = WATERLEVEL_NONE;
+ if(autocvar_cl_movement != 3)
+ {
+ // set watertype/waterlevel
+ origin1 = this.origin;
+ origin1.z += this.mins_z + 1;
+ this.waterlevel = WATERLEVEL_NONE;
- int thepoint = pointcontents(origin1);
+ int thepoint = pointcontents(origin1);
- this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
+ this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
- if (this.watertype)
- {
- this.waterlevel = WATERLEVEL_WETFEET;
- origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
- thepoint = pointcontents(origin1);
- if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+ if (this.watertype)
{
- this.waterlevel = WATERLEVEL_SWIMMING;
- origin1.z = this.origin.z + 22;
+ this.waterlevel = WATERLEVEL_WETFEET;
+ origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
thepoint = pointcontents(origin1);
if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
- this.waterlevel = WATERLEVEL_SUBMERGED;
+ {
+ this.waterlevel = WATERLEVEL_SWIMMING;
+ origin1.z = this.origin.z + 22;
+ thepoint = pointcontents(origin1);
+ if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+ this.waterlevel = WATERLEVEL_SUBMERGED;
+ }
}
}
if (IS_ONGROUND(this) || this.velocity.z <= 0 || pmove_waterjumptime <= 0)
pmove_waterjumptime = 0;
+#endif
}
void PM_ClientMovement_Move(entity this)
f = (this.velocity * trace1_plane_normal);
this.velocity = this.velocity + -f * trace1_plane_normal;
}
- if(pmove_waterjumptime > 0)
+ if(PHYS_TELEPORT_TIME(this) > 0)
this.velocity = primalvelocity;
#endif
}
animdecide_setaction(this, ANIMACTION_JUMP, true);
if (autocvar_g_jump_grunt)
- WITH(entity, this, this, PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND));
+ PlayerSound(this, playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
#endif
return true;
}
this.velocity_z = 225;
this.flags |= FL_WATERJUMP;
SET_JUMP_HELD(this);
-#ifdef SVQC
- this.teleport_time = time + 2; // safety net
-#elif defined(CSQC)
+ #ifdef SVQC
+ PHYS_TELEPORT_TIME(this) = time + 2; // safety net
+ #elif defined(CSQC)
pmove_waterjumptime = time + 2;
-#endif
+ #endif
}
}
}
void SpecialCommand()
{
#ifdef SVQC
- if (!CheatImpulse(99))
+ if (!CheatImpulse(CHIMPULSE_GIVE_ALL.impulse))
LOG_INFO("A hollow voice says \"Plugh\".\n");
#endif
}
void PM_check_hitground(entity this)
{
#ifdef SVQC
- if (!IS_PLAYER(this)) return; // no fall sounds for observers thank you very much
- if (!IS_ONGROUND(this)) return;
if (!this.wasFlying) return;
this.wasFlying = false;
if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
this.nextstep = time + 0.3 + random() * 0.1;
trace_dphitq3surfaceflags = 0;
tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
- if ((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS)) return;
- entity fall = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) ? GS_FALL_METAL : GS_FALL;
- WITH(entity, self, this, GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND));
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
+ entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+ ? GS_FALL_METAL
+ : GS_FALL;
+ GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+#endif
+}
+
+void PM_Footsteps(entity this)
+{
+#ifdef SVQC
+ if (!g_footsteps) return;
+ if (IS_DUCKED(this)) return;
+ if (time >= this.lastground + 0.2) return;
+ if (vdist(this.velocity, <=, autocvar_sv_maxspeed * 0.6)) return;
+ if ((time > this.nextstep) || (time < (this.nextstep - 10.0)))
+ {
+ this.nextstep = time + 0.3 + random() * 0.1;
+ trace_dphitq3surfaceflags = 0;
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
+ entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+ ? GS_STEP_METAL
+ : GS_STEP;
+ GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ }
#endif
}
vector wishdir = normalize(wishvel);
float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
#ifdef SVQC
- if (time >= this.teleport_time)
+ if(time >= PHYS_TELEPORT_TIME(this))
#endif
PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
PM_ClientMovement_Move(this);
{
this.velocity = forward * 50;
this.velocity_z = 310;
+ #ifdef CSQC
pmove_waterjumptime = 2;
+ #endif
UNSET_ONGROUND(this);
SET_JUMP_HELD(this);
}
UNSET_ONGROUND(this);
float g;
- g = PHYS_GRAVITY * PHYS_INPUT_TIMELENGTH;
+ g = PHYS_GRAVITY(this) * PHYS_INPUT_TIMELENGTH;
if (PHYS_ENTGRAVITY(this))
g *= PHYS_ENTGRAVITY(this);
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
// acceleration
vector wishdir = normalize(wishvel);
float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
-#ifdef SVQC
- if (time >= this.teleport_time)
-#endif
+ if(time >= PHYS_TELEPORT_TIME(this))
// water acceleration
PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0);
PM_ClientMovement_Move(this);
// it is now normalized, so...
float a_side = PHYS_JETPACK_ACCEL_SIDE;
float a_up = PHYS_JETPACK_ACCEL_UP;
- float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY;
+ float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY(this);
wishvel_x *= a_side;
wishvel_y *= a_side;
float fxy, fz;
fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
- if (wishvel_z - PHYS_GRAVITY > 0)
+ if (wishvel_z - PHYS_GRAVITY(this) > 0)
fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
else
fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
fvel = vlen(wishvel);
wishvel_x *= fxy;
wishvel_y *= fxy;
- wishvel_z = (wishvel_z - PHYS_GRAVITY) * fz + PHYS_GRAVITY;
+ wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
fvel = min(1, vlen(wishvel) / best);
if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
}
#ifdef CSQC
- float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
if(autocvar_cl_movement != 3)
{
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
this.velocity += accelspeed * wishdir;
}
#ifdef CSQC
- const float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
if(autocvar_cl_movement != 3)
{
if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
float wishspeed = vlen(wishvel);
#ifdef SVQC
- if (time >= this.teleport_time)
-#else
- if (pmove_waterjumptime <= 0)
+ if(time >= PHYS_TELEPORT_TIME(this))
+#elif defined(CSQC)
+ if(pmove_waterjumptime <= 0)
#endif
{
float maxairspd = PHYS_MAXAIRSPEED(this) * min(maxspd_mod, 1);
CPM_PM_Aircontrol(this, wishdir, wishspeed2);
}
#ifdef CSQC
- float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
if(autocvar_cl_movement != 3)
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
this.velocity_z -= g * 0.5;
stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
}
- if(this.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN)
+ if(this.jumpspeedcap_min != autocvar_sv_jumpspeedcap_min)
{
- this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
- stuffcmd(this, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n"));
+ this.jumpspeedcap_min = autocvar_sv_jumpspeedcap_min;
+ stuffcmd(this, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
}
- if(this.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX)
+ if(this.jumpspeedcap_max != autocvar_sv_jumpspeedcap_max)
{
- this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX;
- stuffcmd(this, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n"));
+ this.jumpspeedcap_max = autocvar_sv_jumpspeedcap_max;
+ stuffcmd(this, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
}
#endif
this.angles = '0 1 0' * this.v_angle.y;
#endif
- PM_check_hitground(this);
+ if (IS_PLAYER(this) && IS_ONGROUND(this))
+ {
+ PM_check_hitground(this);
+ PM_Footsteps(this);
+ }
if(IsFlying(this))
this.wasFlying = 1;
{
this.velocity_x = this.movedir.x;
this.velocity_y = this.movedir.y;
- if (time > this.teleport_time || this.waterlevel == WATERLEVEL_NONE)
+ if (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE)
{
this.flags &= ~FL_WATERJUMP;
- this.teleport_time = 0;
+ PHYS_TELEPORT_TIME(this) = 0;
}
}
else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod))
{ }
+#ifdef SVQC
else if (this.movetype == MOVETYPE_NOCLIP || this.movetype == MOVETYPE_FLY || this.movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
+#elif defined(CSQC)
+ else if (this.move_movetype == MOVETYPE_NOCLIP || this.move_movetype == MOVETYPE_FLY || this.move_movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
+#endif
PM_fly(this, maxspeed_mod);
else if (this.waterlevel >= WATERLEVEL_SWIMMING)
SELFPARAM();
#endif
PM_Main(this);
-#ifdef CSQC
- this.pmove_flags =
- ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
- (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) |
- ((this.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
-#endif
}
bool IsFlying(entity a);
+#define BUFFS_STAT(s) STAT(BUFFS, s)
+
+#define GAMEPLAYFIX_DOWNTRACEONGROUND STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, this)
+#define GAMEPLAYFIX_EASIERWATERJUMP STAT(GAMEPLAYFIX_EASIERWATERJUMP, this)
+#define GAMEPLAYFIX_STEPDOWN STAT(GAMEPLAYFIX_STEPDOWN, this)
+#define GAMEPLAYFIX_STEPMULTIPLETIMES STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, this)
+#define GAMEPLAYFIX_UNSTICKPLAYERS STAT(GAMEPLAYFIX_UNSTICKPLAYERS, this)
+
+#define PHYS_ACCELERATE(s) STAT(MOVEVARS_ACCELERATE, s)
+#define PHYS_AIRACCELERATE(s) STAT(MOVEVARS_AIRACCELERATE, s)
+#define PHYS_AIRACCEL_QW(s) STAT(MOVEVARS_AIRACCEL_QW, s)
+#define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, s)
+#define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s) STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, s)
+#define PHYS_AIRCONTROL(s) STAT(MOVEVARS_AIRCONTROL, s)
+#define PHYS_AIRCONTROL_PENALTY(s) STAT(MOVEVARS_AIRCONTROL_PENALTY, s)
+#define PHYS_AIRCONTROL_POWER(s) STAT(MOVEVARS_AIRCONTROL_POWER, s)
+#define PHYS_AIRSPEEDLIMIT_NONQW(s) STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, s)
+#define PHYS_AIRSTOPACCELERATE(s) STAT(MOVEVARS_AIRSTOPACCELERATE, s)
+#define PHYS_AIRSTRAFEACCELERATE(s) STAT(MOVEVARS_AIRSTRAFEACCELERATE, s)
+#define PHYS_AIRSTRAFEACCEL_QW(s) STAT(MOVEVARS_AIRSTRAFEACCEL_QW, s)
+
+#define PHYS_AMMO_FUEL(s) STAT(FUEL, s)
+
+#define PHYS_DODGING_FROZEN STAT(DODGING_FROZEN, this)
+
+#define PHYS_FRICTION(s) STAT(MOVEVARS_FRICTION, s)
+#define PHYS_FRICTION_ONLAND STAT(MOVEVARS_FRICTION_ONLAND, this)
+#define PHYS_FRICTION_SLICK STAT(MOVEVARS_FRICTION_SLICK, this)
+
+#define PHYS_FROZEN(s) STAT(FROZEN, s)
+
+#define PHYS_HIGHSPEED STAT(MOVEVARS_HIGHSPEED, this)
+
+#define PHYS_JETPACK_ACCEL_SIDE STAT(JETPACK_ACCEL_SIDE, this)
+#define PHYS_JETPACK_ACCEL_UP STAT(JETPACK_ACCEL_UP, this)
+#define PHYS_JETPACK_ANTIGRAVITY STAT(JETPACK_ANTIGRAVITY, this)
+#define PHYS_JETPACK_FUEL STAT(JETPACK_FUEL, this)
+#define PHYS_JETPACK_MAXSPEED_SIDE STAT(JETPACK_MAXSPEED_SIDE, this)
+#define PHYS_JETPACK_MAXSPEED_UP STAT(JETPACK_MAXSPEED_UP, this)
+
+#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, this)
+#define PHYS_JUMPSTEP STAT(MOVEVARS_JUMPSTEP, this)
+#define PHYS_JUMPVELOCITY(s) STAT(MOVEVARS_JUMPVELOCITY, s)
+
+#define PHYS_MAXAIRSPEED(s) STAT(MOVEVARS_MAXAIRSPEED, s)
+#define PHYS_MAXAIRSTRAFESPEED(s) STAT(MOVEVARS_MAXAIRSTRAFESPEED, s)
+#define PHYS_MAXSPEED(s) STAT(MOVEVARS_MAXSPEED, s)
+
+#define PHYS_NOSTEP STAT(NOSTEP, this)
+#define PHYS_STEPHEIGHT STAT(MOVEVARS_STEPHEIGHT, this)
+
+#define PHYS_STOPSPEED(s) STAT(MOVEVARS_STOPSPEED, s)
+
+#define PHYS_TRACK_CANJUMP(s) STAT(MOVEVARS_TRACK_CANJUMP, s)
+
+#define PHYS_WALLFRICTION STAT(MOVEVARS_WALLFRICTION, this)
+
+#define PHYS_WARSOWBUNNY_ACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_ACCEL, s)
+#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, s)
+#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s) STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, s)
+#define PHYS_WARSOWBUNNY_TOPSPEED(s) STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, s)
+#define PHYS_WARSOWBUNNY_TURNACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, s)
+
+#define UPWARD_VELOCITY_CLEARS_ONGROUND STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, this)
+
#ifdef CSQC
+ string autocvar_cl_jumpspeedcap_min;
+ string autocvar_cl_jumpspeedcap_max;
+
+ noref float pmove_waterjumptime;
+
const int FL_WATERJUMP = 2048; // player jumping out of water
const int FL_JUMPRELEASED = 4096; // for jump debouncing
// TODO
#define IS_CLIENT(s) (s).isplayermodel
#define IS_PLAYER(s) (s).isplayermodel
+ #define IS_NOT_A_CLIENT(s) !(s).isplayermodel
#define isPushable(s) (s).isplayermodel
//float player_multijump;
//float player_jumpheight;
+ #define PHYS_GRAVITY(s) STAT(MOVEVARS_GRAVITY, s)
+
+ #define PHYS_TELEPORT_TIME(s) s.teleport_time
+
+ #define TICRATE ticrate
+
#define PHYS_INPUT_ANGLES(s) input_angles
// TODO
#define PHYS_WORLD_ANGLES(s) input_angles
#define PHYS_DEAD(s) s.csqcmodel_isdead
- #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- #define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
- #define GAMEPLAYFIX_Q2AIRACCELERATE cvar("sv_gameplayfix_q2airaccelerate")
- #define GAMEPLAYFIX_EASIERWATERJUMP getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
- #define GAMEPLAYFIX_DOWNTRACEONGROUND getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
- #define GAMEPLAYFIX_STEPMULTIPLETIMES getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
- #define GAMEPLAYFIX_UNSTICKPLAYERS getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
- #define GAMEPLAYFIX_STEPDOWN getstati(STAT_GAMEPLAYFIX_STEPDOWN)
+ #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE (boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE))
+ #define GAMEPLAYFIX_NOGRAVITYONGROUND (boolean(moveflags & MOVEFLAG_NOGRAVITYONGROUND))
+ #define GAMEPLAYFIX_Q2AIRACCELERATE (boolean(moveflags & MOVEFLAG_Q2AIRACCELERATE))
#define IS_DUCKED(s) boolean(s.flags & FL_DUCKED)
#define SET_DUCKED(s) s.flags |= FL_DUCKED
#define WAS_ONGROUND(s) boolean(s.lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) (s).items
- #define BUFFS_STAT(s) getstati(STAT_BUFFS)
-
- #define PHYS_AMMO_FUEL(s) getstati(STAT_FUEL)
-
- #define PHYS_FROZEN(s) getstati(STAT_FROZEN)
-
- #define PHYS_JUMPSPEEDCAP_MIN cvar_string("cl_jumpspeedcap_min")
- #define PHYS_JUMPSPEEDCAP_MAX cvar_string("cl_jumpspeedcap_max")
- #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
-
- #define PHYS_CL_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
- #define PHYS_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_TRACK_CANJUMP)
- #define PHYS_ACCELERATE(s) getstatf(STAT_MOVEVARS_ACCELERATE)
- #define PHYS_AIRACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRACCEL_QW)
- #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) getstatf(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR)
- #define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s) getstatf(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION)
- #define PHYS_AIRACCELERATE(s) getstatf(STAT_MOVEVARS_AIRACCELERATE)
- #define PHYS_AIRCONTROL(s) getstatf(STAT_MOVEVARS_AIRCONTROL)
- #define PHYS_AIRCONTROL_PENALTY(s) getstatf(STAT_MOVEVARS_AIRCONTROL_PENALTY)
- #define PHYS_AIRCONTROL_POWER(s) getstatf(STAT_MOVEVARS_AIRCONTROL_POWER)
- #define PHYS_AIRSPEEDLIMIT_NONQW(s) getstatf(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW)
- #define PHYS_AIRSTOPACCELERATE(s) getstatf(STAT_MOVEVARS_AIRSTOPACCELERATE)
- #define PHYS_AIRSTRAFEACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCEL_QW)
- #define PHYS_AIRSTRAFEACCELERATE(s) getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
- #define PHYS_ENTGRAVITY(s) getstatf(STAT_MOVEVARS_ENTGRAVITY)
- #define PHYS_FRICTION(s) getstatf(STAT_MOVEVARS_FRICTION)
- #define PHYS_FRICTION_SLICK getstatf(STAT_MOVEVARS_FRICTION_SLICK)
- #define PHYS_FRICTION_ONLAND getstatf(STAT_MOVEVARS_FRICTION_ONLAND)
- #define PHYS_GRAVITY getstatf(STAT_MOVEVARS_GRAVITY)
- #define PHYS_HIGHSPEED getstatf(STAT_MOVEVARS_HIGHSPEED)
- #define PHYS_JUMPVELOCITY(s) getstatf(STAT_MOVEVARS_JUMPVELOCITY)
- #define PHYS_MAXAIRSPEED(s) getstatf(STAT_MOVEVARS_MAXAIRSPEED)
- #define PHYS_MAXAIRSTRAFESPEED(s) getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
- #define PHYS_MAXSPEED(s) getstatf(STAT_MOVEVARS_MAXSPEED)
- #define PHYS_STEPHEIGHT getstatf(STAT_MOVEVARS_STEPHEIGHT)
- #define PHYS_STOPSPEED(s) getstatf(STAT_MOVEVARS_STOPSPEED)
- #define PHYS_WARSOWBUNNY_ACCEL(s) getstatf(STAT_MOVEVARS_WARSOWBUNNY_ACCEL)
- #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s) getstatf(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO)
- #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s) getstatf(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL)
- #define PHYS_WARSOWBUNNY_TOPSPEED(s) getstatf(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED)
- #define PHYS_WARSOWBUNNY_TURNACCEL(s) getstatf(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL)
-
- #define PHYS_WALLFRICTION getstati(STAT_MOVEVARS_WALLFRICTION)
-
- #define PHYS_JETPACK_ACCEL_UP getstatf(STAT_JETPACK_ACCEL_UP)
- #define PHYS_JETPACK_ACCEL_SIDE getstatf(STAT_JETPACK_ACCEL_SIDE)
- #define PHYS_JETPACK_ANTIGRAVITY getstatf(STAT_JETPACK_ANTIGRAVITY)
- #define PHYS_JETPACK_FUEL getstatf(STAT_JETPACK_FUEL)
- #define PHYS_JETPACK_MAXSPEED_UP getstatf(STAT_JETPACK_MAXSPEED_UP)
- #define PHYS_JETPACK_MAXSPEED_SIDE getstatf(STAT_JETPACK_MAXSPEED_SIDE)
-
- #define PHYS_DODGING_FROZEN getstati(STAT_DODGING_FROZEN)
-
- #define PHYS_NOSTEP getstati(STAT_NOSTEP)
- #define PHYS_JUMPSTEP getstati(STAT_MOVEVARS_JUMPSTEP)
+
+ #define PHYS_JUMPSPEEDCAP_MIN autocvar_cl_jumpspeedcap_min
+ #define PHYS_JUMPSPEEDCAP_MAX autocvar_cl_jumpspeedcap_max
+
+ #define PHYS_CL_TRACK_CANJUMP(s) STAT(MOVEVARS_CL_TRACK_CANJUMP, s)
+ // FIXME: 0 doesn't mean zero gravity
+ #define PHYS_ENTGRAVITY(s) STAT(MOVEVARS_ENTGRAVITY, s)
#elif defined(SVQC)
bool Physics_Valid(string thecvar);
- .vector stat_pl_view_ofs;
- .vector stat_pl_crouch_view_ofs;
-
- .vector stat_pl_min;
- .vector stat_pl_max;
- .vector stat_pl_crouch_min;
- .vector stat_pl_crouch_max;
-
- .float stat_sv_airaccel_qw;
- .float stat_sv_airstrafeaccel_qw;
- .float stat_sv_airspeedlimit_nonqw;
- .float stat_sv_maxspeed;
- .float stat_movement_highspeed;
-
- .float stat_sv_friction_on_land;
- .float stat_sv_friction_slick;
-
- .string stat_jumpspeedcap_min;
- .string stat_jumpspeedcap_max;
- .float stat_jumpspeedcap_disable_onramps;
-
- .float stat_jetpack_accel_side;
- .float stat_jetpack_accel_up;
- .float stat_jetpack_antigravity;
- .float stat_jetpack_fuel;
- .float stat_jetpack_maxspeed_up;
- .float stat_jetpack_maxspeed_side;
- .float stat_gameplayfix_easierwaterjump;
- .float stat_gameplayfix_downtracesupportsongroundflag;
- .float stat_gameplayfix_stepmultipletimes;
- .float stat_gameplayfix_unstickplayers;
- .float stat_gameplayfix_stepdown;
-
- // new properties
- .float stat_sv_jumpvelocity;
- .float stat_sv_airaccel_qw_stretchfactor;
- .float stat_sv_maxairstrafespeed;
- .float stat_sv_maxairspeed;
- .float stat_sv_airstrafeaccelerate;
- .float stat_sv_warsowbunny_turnaccel;
- .float stat_sv_airaccel_sideways_friction;
- .float stat_sv_aircontrol;
- .float stat_sv_aircontrol_power;
- .float stat_sv_aircontrol_penalty;
- .float stat_sv_warsowbunny_airforwardaccel;
- .float stat_sv_warsowbunny_topspeed;
- .float stat_sv_warsowbunny_accel;
- .float stat_sv_warsowbunny_backtosideratio;
- .float stat_sv_friction;
- .float stat_sv_accelerate;
- .float stat_sv_stopspeed;
- .float stat_sv_airaccelerate;
- .float stat_sv_airstopaccelerate;
-
- .float stat_nostep;
- .float stat_jumpstep;
-
- .bool stat_sv_track_canjump;
+ .float stat_sv_airspeedlimit_nonqw = _STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW);
+ .float stat_sv_maxspeed = _STAT(MOVEVARS_MAXSPEED);
+
+ /** Not real stats */
+ .string jumpspeedcap_min;
+ .string jumpspeedcap_max;
+
+ #define PHYS_TELEPORT_TIME(s) s.teleport_time
+
+ #define PHYS_GRAVITY(s) autocvar_sv_gravity
+
+ #define TICRATE sys_frametime
#define PHYS_INPUT_ANGLES(s) s.v_angle
#define PHYS_WORLD_ANGLES(s) s.angles
#define PHYS_DEAD(s) s.deadflag != DEAD_NO
#define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
- #define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
+ #define GAMEPLAYFIX_NOGRAVITYONGROUND autocvar_sv_gameplayfix_nogravityonground
#define GAMEPLAYFIX_Q2AIRACCELERATE autocvar_sv_gameplayfix_q2airaccelerate
- #define GAMEPLAYFIX_EASIERWATERJUMP cvar("sv_gameplayfix_easierwaterjump")
- #define GAMEPLAYFIX_DOWNTRACEONGROUND cvar("sv_gameplayfix_downtracesupportsongroundflag")
- #define GAMEPLAYFIX_STEPMULTIPLETIMES cvar("sv_gameplayfix_stepmultipletimes")
- #define GAMEPLAYFIX_UNSTICKPLAYERS cvar("sv_gameplayfix_unstickplayers")
- #define GAMEPLAYFIX_STEPDOWN cvar("sv_gameplayfix_stepdown")
#define IS_DUCKED(s) s.crouch
#define SET_DUCKED(s) s.crouch = true
#define WAS_ONGROUND(s) boolean((s).lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) s.items
- #define BUFFS_STAT(s) (s).buffs
-
- #define PHYS_AMMO_FUEL(s) s.ammo_fuel
-
- #define PHYS_FROZEN(s) s.frozen
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
- #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS autocvar_sv_jumpspeedcap_max_disable_on_ramps
#define PHYS_CL_TRACK_CANJUMP(s) s.cvar_cl_movement_track_canjump
- #define PHYS_TRACK_CANJUMP(s) s.stat_sv_track_canjump
- #define PHYS_ACCELERATE(s) s.stat_sv_accelerate
- #define PHYS_AIRACCEL_QW(s) s.stat_sv_airaccel_qw
- #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) s.stat_sv_airaccel_qw_stretchfactor
- #define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s) s.stat_sv_airaccel_sideways_friction
- #define PHYS_AIRACCELERATE(s) s.stat_sv_airaccelerate
- #define PHYS_AIRCONTROL(s) s.stat_sv_aircontrol
- #define PHYS_AIRCONTROL_PENALTY(s) s.stat_sv_aircontrol_penalty
- #define PHYS_AIRCONTROL_POWER(s) s.stat_sv_aircontrol_power
- #define PHYS_AIRSPEEDLIMIT_NONQW(s) s.stat_sv_airspeedlimit_nonqw
- #define PHYS_AIRSTOPACCELERATE(s) s.stat_sv_airstopaccelerate
- #define PHYS_AIRSTRAFEACCEL_QW(s) s.stat_sv_airstrafeaccel_qw
- #define PHYS_AIRSTRAFEACCELERATE(s) s.stat_sv_airstrafeaccelerate
#define PHYS_ENTGRAVITY(s) s.gravity
- #define PHYS_FRICTION(s) s.stat_sv_friction
- #define PHYS_FRICTION_SLICK autocvar_sv_friction_slick
- #define PHYS_FRICTION_ONLAND autocvar_sv_friction_on_land
- #define PHYS_GRAVITY autocvar_sv_gravity
- #define PHYS_HIGHSPEED autocvar_g_movement_highspeed
- #define PHYS_JUMPVELOCITY(s) s.stat_sv_jumpvelocity
- #define PHYS_MAXAIRSPEED(s) s.stat_sv_maxairspeed
- #define PHYS_MAXAIRSTRAFESPEED(s) s.stat_sv_maxairstrafespeed
- #define PHYS_MAXSPEED(s) s.stat_sv_maxspeed
- #define PHYS_STEPHEIGHT autocvar_sv_stepheight
- #define PHYS_STOPSPEED(s) s.stat_sv_stopspeed
- #define PHYS_WARSOWBUNNY_ACCEL(s) s.stat_sv_warsowbunny_accel
- #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)s.stat_sv_warsowbunny_backtosideratio
- #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)s.stat_sv_warsowbunny_airforwardaccel
- #define PHYS_WARSOWBUNNY_TOPSPEED(s) s.stat_sv_warsowbunny_topspeed
- #define PHYS_WARSOWBUNNY_TURNACCEL(s) s.stat_sv_warsowbunny_turnaccel
-
- #define PHYS_WALLFRICTION cvar("sv_wallfriction")
-
- #define PHYS_JETPACK_ACCEL_UP autocvar_g_jetpack_acceleration_up
- #define PHYS_JETPACK_ACCEL_SIDE autocvar_g_jetpack_acceleration_side
- #define PHYS_JETPACK_ANTIGRAVITY autocvar_g_jetpack_antigravity
- #define PHYS_JETPACK_FUEL autocvar_g_jetpack_fuel
- #define PHYS_JETPACK_MAXSPEED_UP autocvar_g_jetpack_maxspeed_up
- #define PHYS_JETPACK_MAXSPEED_SIDE autocvar_g_jetpack_maxspeed_side
-
- #define PHYS_DODGING_FROZEN autocvar_sv_dodging_frozen
-
- #define PHYS_NOSTEP cvar("sv_nostep")
- #define PHYS_JUMPSTEP cvar("sv_jumpstep")
#endif
#endif
void PlayerStats_GameReport_Accuracy(entity p)
{
- int i;
-
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- entity w = get_weaponinfo(i);
-
- #define ACCMAC(suffix,field) \
- PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", w.netname, suffix), p.accuracy.(field[i-1]));
-
+ #define ACCMAC(suffix, field) \
+ PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", it.netname, suffix), p.accuracy.(field[i-1]));
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
ACCMAC("hit", accuracy_hit)
ACCMAC("fired", accuracy_fired)
ACCMAC("cnt-hit", accuracy_cnt_hit)
ACCMAC("cnt-fired", accuracy_cnt_fired)
ACCMAC("frags", accuracy_frags)
-
- #undef ACCMAC
- }
+ ));
+ #undef ACCMAC
}
void PlayerStats_GameReport_FinalizePlayer(entity p)
PlayerStats_GameReport_AddEvent(PLAYERSTATS_RANK);
// accuracy stats
- entity w;
- float i;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- w = get_weaponinfo(i);
- PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-hit"));
- PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-fired"));
- PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-hit"));
- PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-fired"));
- PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-frags"));
- }
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-hit"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-fired"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-cnt-hit"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-cnt-fired"));
+ PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-frags"));
+ ));
PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3);
PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5);
#define sound8(e, o, chan, samp, vol, atten, speed, sf) \
do \
{ \
- entity __e = e; \
+ entity __e; \
+ int __chan = chan; \
+ string __samp = samp; \
+ bool auto = false; \
+ if (__chan > 0) __e = e; \
+ else \
+ { \
+ auto = true; \
+ __chan = fabs(__chan); \
+ entity tmp = __e = new(csqc_autochannel); \
+ make_pure(tmp); \
+ tmp.think = SUB_Remove_self; \
+ tmp.nextthink = time + soundlength(__samp); \
+ } \
vector old_origin = __e.origin; \
vector old_mins = __e.mins; \
vector old_maxs = __e.maxs; \
setorigin(__e, o); \
setsize(__e, '0 0 0', '0 0 0'); \
- sound7(__e, chan, samp, vol, atten, speed, sf); \
+ sound7(__e, __chan, __samp, vol, atten, speed, sf); \
+ if (auto) break; \
setorigin(__e, old_origin); \
setsize(__e, old_mins, old_maxs); \
} \
x(ogg) \
x(flac) \
/**/
- string full, relative;
- #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
+ string relative;
+ #define tryext(ext) { if (fexists(strcat("sound/", relative = strcat(base, "." #ext)))) break; }
do
{
extensions(tryext);
#undef tryext
#undef extensions
- LOG_WARNINGF("Missing sound: \"%s\"\n", full);
+ LOG_WARNINGF("Missing sound: \"%s\"\n", strcat("sound/", base));
+#ifdef CSQC
return string_null;
+#endif
}
while (0);
+#ifdef SVQC
+ return strcat(base, ".wav"); // let the client engine decide
+#else
return relative;
+#endif
}
METHOD(Sound, sound_precache, void(entity this))
{
#ifndef STATS_H
#define STATS_H
+#ifdef SVQC
+#include "../server/cl_client.qh"
+#endif
+
// Full list of all stat constants, included in a single location for easy reference
// 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
-const int MAX_CL_STATS = 256;
-// -Wdouble-declaration
-// const int STAT_HEALTH = 0;
-// 1 empty?
-const int STAT_WEAPON = 2;
-// -Wdouble-declaration
-// const int STAT_AMMO = 3;
-// -Wdouble-declaration
-// const int STAT_ARMOR = 4;
-// -Wdouble-declaration
-// const int STAT_WEAPONFRAME = 5;
-// -Wdouble-declaration
-// const int STAT_SHELLS = 6;
-// -Wdouble-declaration
-// const int STAT_NAILS = 7;
-// -Wdouble-declaration
-// const int STAT_ROCKETS = 8;
-// -Wdouble-declaration
-// const int STAT_CELLS = 9;
-// -Wdouble-declaration
-// const int STAT_ACTIVEWEAPON = 10;
-// -Wdouble-declaration
-// const int STAT_TOTALSECRETS = 11;
-// -Wdouble-declaration
-// const int STAT_TOTALMONSTERS = 12;
-// -Wdouble-declaration
-// const int STAT_SECRETS = 13;
-// -Wdouble-declaration
-// const int STAT_MONSTERS = 14;
-// -Wdouble-declaration
-// const int STAT_ITEMS = 15;
-// -Wdouble-declaration
-// const int STAT_VIEWHEIGHT = 16;
-// 17 empty?
-// 18 empty?
-// 19 empty?
-// 20 empty?
-const int STAT_VIEWZOOM = 21;
-// 22 empty?
-// 23 empty?
-// 24 empty?
-// 25 empty?
-// 26 empty?
-// 27 empty?
-// 28 empty?
-// 29 empty?
-// 30 empty?
-// 31 empty?
-
-enum {
- STAT_WEAPONS = 32,
- STAT_WEAPONS2,
- STAT_WEAPONS3,
-
- STAT_WEAPONSINMAP,
- STAT_WEAPONSINMAP2,
- STAT_WEAPONSINMAP3,
-
- STAT_PL_VIEW_OFS1,
- STAT_PL_VIEW_OFS2,
- STAT_PL_VIEW_OFS3,
-
- STAT_PL_CROUCH_VIEW_OFS1,
- STAT_PL_CROUCH_VIEW_OFS2,
- STAT_PL_CROUCH_VIEW_OFS3,
-
- STAT_PL_MIN1,
- STAT_PL_MIN2,
- STAT_PL_MIN3,
-
- STAT_PL_MAX1,
- STAT_PL_MAX2,
- STAT_PL_MAX3,
+const int MAX_CL_STATS = 256;
+#ifndef CSQC
+const int STAT_HEALTH = 0; // .health
+const int STAT_ARMOR = 4; // .armorvalue
+const int STAT_SHELLS = 6; // .ammo_shells
+const int STAT_NAILS = 7; // .ammo_nails
+const int STAT_ROCKETS = 8; // .ammo_rockets
+const int STAT_CELLS = 9; // .ammo_cells
+const int STAT_ACTIVEWEAPON = 10; // .weapon
+const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28
+const int STAT_VIEWHEIGHT = 16; // .view_ofs_z
+#endif
- STAT_PL_CROUCH_MIN1,
- STAT_PL_CROUCH_MIN2,
- STAT_PL_CROUCH_MIN3,
+REGISTER_STAT(WEAPONS, vectori)
+REGISTER_STAT(WEAPONSINMAP, vectori)
- STAT_PL_CROUCH_MAX1,
- STAT_PL_CROUCH_MAX2,
- STAT_PL_CROUCH_MAX3,
+REGISTER_STAT(PL_VIEW_OFS, vector, autocvar_sv_player_viewoffset)
+REGISTER_STAT(PL_CROUCH_VIEW_OFS, vector, autocvar_sv_player_crouch_viewoffset)
- STAT_LAST_VECTOR
-};
+REGISTER_STAT(PL_MIN, vector, autocvar_sv_player_mins)
+REGISTER_STAT(PL_CROUCH_MIN, vector, autocvar_sv_player_crouch_mins)
-const int REGISTERED_STATS = 6;
+REGISTER_STAT(PL_MAX, vector, autocvar_sv_player_maxs)
+REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs)
REGISTER_STAT(KH_KEYS, int)
+
/** weapon requested to switch to; next WANTED weapon (for HUD) */
REGISTER_STAT(SWITCHWEAPON, int)
+/** weapon currently being switched to (is copied from switchweapon once switch is possible) */
+REGISTER_STAT(SWITCHINGWEAPON, int)
+REGISTER_STAT(WEAPON_NEXTTHINK, float)
+#ifdef SVQC
+SPECTATE_COPY(_STAT(WEAPON_NEXTTHINK))
+float W_WeaponRateFactor();
+#endif
+REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor())
+
REGISTER_STAT(GAMESTARTTIME, float)
REGISTER_STAT(STRENGTH_FINISHED, float)
REGISTER_STAT(INVINCIBLE_FINISHED, float)
/** arc heat in [0,1] */
REGISTER_STAT(ARC_HEAT, float)
+REGISTER_STAT(PRESSED_KEYS, int)
+/** this stat could later contain some other bits of info, like, more server-side particle config */
+REGISTER_STAT(ALLOW_OLDVORTEXBEAM, bool)
+REGISTER_STAT(FUEL, int)
+REGISTER_STAT(NB_METERSTART, float)
+/** compressShotOrigin */
+REGISTER_STAT(SHOTORG, int)
+REGISTER_STAT(LEADLIMIT, float)
+REGISTER_STAT(WEAPON_CLIPLOAD, int)
+REGISTER_STAT(WEAPON_CLIPSIZE, int)
-enum {
- STAT_FIRST_MAIN = (STAT_LAST_VECTOR - 1) + REGISTERED_STATS,
+REGISTER_STAT(VORTEX_CHARGE, float)
+REGISTER_STAT(LAST_PICKUP, float)
+REGISTER_STAT(HUD, int)
+REGISTER_STAT(VORTEX_CHARGEPOOL, float)
+REGISTER_STAT(HIT_TIME, float)
+REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
+REGISTER_STAT(TYPEHIT_TIME, float)
+REGISTER_STAT(LAYED_MINES, int)
+REGISTER_STAT(HAGAR_LOAD, int)
+REGISTER_STAT(SUPERWEAPONS_FINISHED, float)
+REGISTER_STAT(VEHICLESTAT_HEALTH, int)
+REGISTER_STAT(VEHICLESTAT_SHIELD, int)
+REGISTER_STAT(VEHICLESTAT_ENERGY, int)
+REGISTER_STAT(VEHICLESTAT_AMMO1, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD1, int)
+REGISTER_STAT(VEHICLESTAT_AMMO2, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
+REGISTER_STAT(VEHICLESTAT_W2MODE, int)
+REGISTER_STAT(NADE_TIMER, float)
+REGISTER_STAT(SECRETS_TOTAL, float)
+REGISTER_STAT(SECRETS_FOUND, float)
+REGISTER_STAT(RESPAWN_TIME, float)
+REGISTER_STAT(ROUNDSTARTTIME, float)
+REGISTER_STAT(MONSTERS_TOTAL, int)
+REGISTER_STAT(MONSTERS_KILLED, int)
+REGISTER_STAT(BUFFS, int)
+REGISTER_STAT(NADE_BONUS, float)
+REGISTER_STAT(NADE_BONUS_TYPE, int)
+REGISTER_STAT(NADE_BONUS_SCORE, float)
+REGISTER_STAT(HEALING_ORB, float)
+REGISTER_STAT(HEALING_ORB_ALPHA, float)
+REGISTER_STAT(PLASMA, int)
+REGISTER_STAT(OK_AMMO_CHARGE, float)
+REGISTER_STAT(OK_AMMO_CHARGEPOOL, float)
+REGISTER_STAT(FROZEN, int)
+REGISTER_STAT(REVIVE_PROGRESS, float)
+REGISTER_STAT(ROUNDLOST, int)
+REGISTER_STAT(BUFF_TIME, float)
+REGISTER_STAT(CTF_FLAGSTATUS, int)
- STAT_PRESSED_KEYS,
- /** this stat could later contain some other bits of info, like, more server-side particle config */ STAT_ALLOW_OLDVORTEXBEAM,
- STAT_FUEL,
- STAT_NB_METERSTART,
- /** compressShotOrigin */ STAT_SHOTORG,
- STAT_LEADLIMIT,
- STAT_WEAPON_CLIPLOAD,
- STAT_WEAPON_CLIPSIZE,
- STAT_VORTEX_CHARGE,
- STAT_LAST_PICKUP,
- STAT_HUD,
- STAT_VORTEX_CHARGEPOOL,
- STAT_HIT_TIME,
- STAT_DAMAGE_DEALT_TOTAL,
- STAT_TYPEHIT_TIME,
- STAT_LAYED_MINES,
- STAT_HAGAR_LOAD,
- STAT_SWITCHINGWEAPON,
- STAT_SUPERWEAPONS_FINISHED,
- STAT_VEHICLESTAT_HEALTH,
- STAT_VEHICLESTAT_SHIELD,
- STAT_VEHICLESTAT_ENERGY,
- STAT_VEHICLESTAT_AMMO1,
- STAT_VEHICLESTAT_RELOAD1,
- STAT_VEHICLESTAT_AMMO2,
- STAT_VEHICLESTAT_RELOAD2,
- STAT_VEHICLESTAT_W2MODE,
- STAT_NADE_TIMER,
- STAT_SECRETS_TOTAL,
- STAT_SECRETS_FOUND,
- STAT_RESPAWN_TIME,
- STAT_ROUNDSTARTTIME,
- STAT_MONSTERS_TOTAL,
- STAT_MONSTERS_KILLED,
- STAT_BUFFS,
- STAT_NADE_BONUS,
- STAT_NADE_BONUS_TYPE,
- STAT_NADE_BONUS_SCORE,
- STAT_HEALING_ORB,
- STAT_HEALING_ORB_ALPHA,
- STAT_PLASMA,
- STAT_OK_AMMO_CHARGE,
- STAT_OK_AMMO_CHARGEPOOL,
- STAT_FROZEN,
- STAT_REVIVE_PROGRESS,
- STAT_ROUNDLOST,
- STAT_BUFF_TIME,
- STAT_CTF_FLAGSTATUS,
- STAT_MULTIJUMP_DODGING,
- STAT_MULTIJUMP_MAXSPEED,
- STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND,
- STAT_BUGRIGS_REVERSE_STOPPING,
- STAT_BUGRIGS_REVERSE_SPINNING,
- STAT_BUGRIGS_CAR_JUMPING,
- STAT_BUGRIGS_FRICTION_AIR,
- STAT_BUGRIGS_STEER,
- STAT_BUGRIGS_SPEED_POW,
- STAT_BUGRIGS_SPEED_REF,
- STAT_BUGRIGS_ACCEL,
- STAT_BUGRIGS_FRICTION_BRAKE,
- STAT_BUGRIGS_AIR_STEERING,
- STAT_BUGRIGS_FRICTION_FLOOR,
- STAT_BUGRIGS_REVERSE_SPEEDING,
- STAT_BUGRIGS_PLANAR_MOVEMENT,
- STAT_BUGRIGS_ANGLE_SMOOTHING,
- STAT_BUGRIGS,
- STAT_GAMEPLAYFIX_STEPDOWN,
- STAT_MOVEVARS_JUMPSTEP,
- STAT_NOSTEP,
- STAT_GAMEPLAYFIX_UNSTICKPLAYERS,
- STAT_GAMEPLAYFIX_STEPMULTIPLETIMES,
- STAT_GAMEPLAYFIX_DOWNTRACEONGROUND,
- STAT_GAMEPLAYFIX_EASIERWATERJUMP,
- STAT_MOVEVARS_FRICTION_SLICK,
- STAT_MOVEVARS_FRICTION_ONLAND,
- STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS,
- STAT_MOVEVARS_TRACK_CANJUMP,
- STAT_DOUBLEJUMP,
- STAT_MOVEVARS_CL_TRACK_CANJUMP,
- STAT_MULTIJUMP_ADD,
- STAT_MULTIJUMP_SPEED,
- STAT_MULTIJUMP,
- STAT_DODGING_TIMEOUT,
- STAT_DODGING_WALL,
- STAT_DODGING_UP_SPEED,
- STAT_DODGING_RAMP_TIME,
- STAT_DODGING_HEIGHT_THRESHOLD,
- STAT_DODGING_DISTANCE_THRESHOLD,
- STAT_DODGING_HORIZ_SPEED,
- STAT_DODGING_DELAY,
- STAT_DODGING_FROZEN_NO_DOUBLETAP,
- STAT_DODGING_HORIZ_SPEED_FROZEN,
- STAT_DODGING,
- STAT_DODGING_FROZEN,
- STAT_JETPACK_MAXSPEED_UP,
- STAT_JETPACK_MAXSPEED_SIDE,
- STAT_JETPACK_FUEL,
- STAT_JETPACK_ANTIGRAVITY,
- STAT_JETPACK_ACCEL_SIDE,
- STAT_JETPACK_ACCEL_UP,
- STAT_MOVEVARS_HIGHSPEED,
- STAT_MULTIJUMP_COUNT,
+#ifdef SVQC
+int autocvar_g_multijump;
+float autocvar_g_multijump_add;
+float autocvar_g_multijump_speed;
+float autocvar_g_multijump_maxspeed;
+float autocvar_g_multijump_dodging = 1;
+#endif
+REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
+REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
+REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
+REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+.int multijump_count;
+REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
+REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
+REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump)
+
+#ifdef SVQC
+bool g_bugrigs;
+bool g_bugrigs_planar_movement;
+bool g_bugrigs_planar_movement_car_jumping;
+float g_bugrigs_reverse_spinning;
+float g_bugrigs_reverse_speeding;
+float g_bugrigs_reverse_stopping;
+float g_bugrigs_air_steering;
+float g_bugrigs_angle_smoothing;
+float g_bugrigs_friction_floor;
+float g_bugrigs_friction_brake;
+float g_bugrigs_friction_air;
+float g_bugrigs_accel;
+float g_bugrigs_speed_ref;
+float g_bugrigs_speed_pow;
+float g_bugrigs_steer;
+#endif
+REGISTER_STAT(BUGRIGS, int, g_bugrigs)
+REGISTER_STAT(BUGRIGS_ACCEL, float, g_bugrigs_accel)
+REGISTER_STAT(BUGRIGS_AIR_STEERING, int, g_bugrigs_air_steering)
+REGISTER_STAT(BUGRIGS_ANGLE_SMOOTHING, int, g_bugrigs_angle_smoothing)
+REGISTER_STAT(BUGRIGS_CAR_JUMPING, int, g_bugrigs_planar_movement_car_jumping)
+REGISTER_STAT(BUGRIGS_FRICTION_AIR, float, g_bugrigs_friction_air)
+REGISTER_STAT(BUGRIGS_FRICTION_BRAKE, float, g_bugrigs_friction_brake)
+REGISTER_STAT(BUGRIGS_FRICTION_FLOOR, float, g_bugrigs_friction_floor)
+REGISTER_STAT(BUGRIGS_PLANAR_MOVEMENT, int, g_bugrigs_planar_movement)
+REGISTER_STAT(BUGRIGS_REVERSE_SPEEDING, int, g_bugrigs_reverse_speeding)
+REGISTER_STAT(BUGRIGS_REVERSE_SPINNING, int, g_bugrigs_reverse_spinning)
+REGISTER_STAT(BUGRIGS_REVERSE_STOPPING, int, g_bugrigs_reverse_stopping)
+REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow)
+REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref)
+REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer)
+
+REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag"))
+REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump"))
+REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown"))
+REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes"))
+REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers"))
+REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
+
+REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
+REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
+
+REGISTER_STAT(MOVEVARS_FRICTION, float)
+REGISTER_STAT(MOVEVARS_FRICTION_SLICK, float, autocvar_sv_friction_slick)
+REGISTER_STAT(MOVEVARS_FRICTION_ONLAND, float, autocvar_sv_friction_on_land)
- STAT_LAST_MAIN
-};
+REGISTER_STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, int, autocvar_sv_jumpspeedcap_max_disable_on_ramps)
+REGISTER_STAT(MOVEVARS_TRACK_CANJUMP, int)
+/** cvar loopback */
+REGISTER_STAT(MOVEVARS_CL_TRACK_CANJUMP, int)
-const int STAT_LAST = STAT_LAST_MAIN + 5;
+#ifdef SVQC
+int g_dodging;
+float autocvar_sv_dodging_delay;
+float autocvar_sv_dodging_wall_distance_threshold;
+bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_dodging_frozen_doubletap;
+float autocvar_sv_dodging_height_threshold;
+float autocvar_sv_dodging_horiz_speed;
+float autocvar_sv_dodging_horiz_speed_frozen;
+float autocvar_sv_dodging_ramp_time;
+float autocvar_sv_dodging_up_speed;
+bool autocvar_sv_dodging_wall_dodging;
+#endif
+
+REGISTER_STAT(DODGING, int, g_dodging)
+REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay)
+REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold)
+REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
+REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
+REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold)
+REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed)
+REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen)
+REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time)
+/** cvar loopback */
+REGISTER_STAT(DODGING_TIMEOUT, float)
+REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed)
+REGISTER_STAT(DODGING_WALL, int, autocvar_sv_dodging_wall_dodging)
+
+REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side)
+REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up)
+REGISTER_STAT(JETPACK_ANTIGRAVITY, float, autocvar_g_jetpack_antigravity)
+REGISTER_STAT(JETPACK_FUEL, float, autocvar_g_jetpack_fuel)
+REGISTER_STAT(JETPACK_MAXSPEED_SIDE, float, autocvar_g_jetpack_maxspeed_side)
+REGISTER_STAT(JETPACK_MAXSPEED_UP, float, autocvar_g_jetpack_maxspeed_up)
-/* The following stats change depending on the gamemode, so can share the same ID */
+REGISTER_STAT(MOVEVARS_HIGHSPEED, float, autocvar_g_movement_highspeed)
-// freeze tag, clan arena, jailbreak
-enum {
- STAT_REDALIVE = STAT_LAST_MAIN,
- STAT_BLUEALIVE,
- STAT_YELLOWALIVE,
- STAT_PINKALIVE,
-};
+// freeze tag, clan arena
+REGISTER_STAT(REDALIVE, int)
+REGISTER_STAT(BLUEALIVE, int)
+REGISTER_STAT(YELLOWALIVE, int)
+REGISTER_STAT(PINKALIVE, int)
// domination
-enum {
- STAT_DOM_TOTAL_PPS = STAT_LAST_MAIN,
- STAT_DOM_PPS_RED,
- STAT_DOM_PPS_BLUE,
- STAT_DOM_PPS_YELLOW,
- STAT_DOM_PPS_PINK,
-};
+REGISTER_STAT(DOM_TOTAL_PPS, float)
+REGISTER_STAT(DOM_PPS_RED, float)
+REGISTER_STAT(DOM_PPS_BLUE, float)
+REGISTER_STAT(DOM_PPS_YELLOW, float)
+REGISTER_STAT(DOM_PPS_PINK, float)
-// vip
-enum {
- STAT_VIP = STAT_LAST_MAIN,
- STAT_VIP_RED,
- STAT_VIP_BLUE,
- STAT_VIP_YELLOW,
- STAT_VIP_PINK,
-};
+REGISTER_STAT(TELEPORT_MAXSPEED, float, autocvar_g_teleport_maxspeed)
+REGISTER_STAT(TELEPORT_TELEFRAG_AVOID, int, autocvar_g_telefrags_avoid)
-// key hunt
-enum {
- STAT_KH_REDKEY_TEAM = STAT_LAST_MAIN,
- STAT_KH_BLUEKEY_TEAM,
- STAT_KH_YELLOWKEY_TEAM,
- STAT_KH_PINKKEY_TEAM,
-};
+#ifdef SVQC
+#include "movetypes/movetypes.qh"
+#endif
+
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_PENALTY, float)
+REGISTER_STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float)
+noref bool autocvar_sv_gameplayfix_nogravityonground;
+REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID
+ | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0)
+ | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0)
+ | (autocvar_sv_gameplayfix_gravityunaffectedbyticrate ? MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE : 0))
-#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
-ASSERT_LESS(stat_limit, STAT_LAST, 220)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_ACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, float)
-const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220;
-const int STAT_MOVEVARS_AIRCONTROL_PENALTY = 221;
-const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
-const int STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
-const int STAT_MOVEVARS_AIRCONTROL_POWER = 224;
-const int STAT_MOVEFLAGS = 225;
-const int STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL = 226;
-const int STAT_MOVEVARS_WARSOWBUNNY_ACCEL = 227;
-const int STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED = 228;
-const int STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL = 229;
-const int STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO = 230;
-const int STAT_MOVEVARS_AIRSTOPACCELERATE = 231;
-const int STAT_MOVEVARS_AIRSTRAFEACCELERATE = 232;
-const int STAT_MOVEVARS_MAXAIRSTRAFESPEED = 233;
-const int STAT_MOVEVARS_AIRCONTROL = 234;
-// -Wdouble-declaration
-// const int STAT_FRAGLIMIT = 235;
-// -Wdouble-declaration
-// const int STAT_TIMELIMIT = 236;
-const int STAT_MOVEVARS_WALLFRICTION = 237;
-const int STAT_MOVEVARS_FRICTION = 238;
-const int STAT_MOVEVARS_WATERFRICTION = 239;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TICRATE = 240;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TIMESCALE = 241;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_GRAVITY = 242;
-const int STAT_MOVEVARS_STOPSPEED = 243;
-const int STAT_MOVEVARS_MAXSPEED = 244;
-const int STAT_MOVEVARS_SPECTATORMAXSPEED = 245;
-const int STAT_MOVEVARS_ACCELERATE = 246;
-const int STAT_MOVEVARS_AIRACCELERATE = 247;
-const int STAT_MOVEVARS_WATERACCELERATE = 248;
-const int STAT_MOVEVARS_ENTGRAVITY = 249;
-const int STAT_MOVEVARS_JUMPVELOCITY = 250;
-const int STAT_MOVEVARS_EDGEFRICTION = 251;
-const int STAT_MOVEVARS_MAXAIRSPEED = 252;
-const int STAT_MOVEVARS_STEPHEIGHT = 253;
-const int STAT_MOVEVARS_AIRACCEL_QW = 254;
-const int STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255;
+REGISTER_STAT(MOVEVARS_AIRSTOPACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCELERATE, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSTRAFESPEED, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL, float)
+REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit)
+REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit)
+#ifdef SVQC
+float autocvar_sv_wallfriction;
+#endif
+REGISTER_STAT(MOVEVARS_WALLFRICTION, int, autocvar_sv_wallfriction)
+REGISTER_STAT(MOVEVARS_TICRATE, float, autocvar_sys_ticrate)
+REGISTER_STAT(MOVEVARS_TIMESCALE, float, autocvar_slowmo)
+REGISTER_STAT(MOVEVARS_GRAVITY, float, autocvar_sv_gravity)
+REGISTER_STAT(MOVEVARS_STOPSPEED, float)
+REGISTER_STAT(MOVEVARS_MAXSPEED, float)
+REGISTER_STAT(MOVEVARS_ACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRACCELERATE, float)
+.float gravity;
+// FIXME: Was 0 on server, 1 on client. Still want that?
+REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1)
+REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float)
+REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
#endif
WriteString(MSG_ENTITY, self.model);
- trigger_common_write(true);
+ trigger_common_write(self, true);
WriteCoord(MSG_ENTITY, self.pos1_x);
WriteCoord(MSG_ENTITY, self.pos1_y);
if(IS_VEHICLE(other))
return;
#endif
-#ifdef CSQC
- if(other.classname != "csqcmodel")
- return;
-#endif
EXACTTRIGGER_TOUCH;
}
#ifdef SVQC
-bool func_ladder_send(entity this, entity to, float sf)
-{
+bool func_ladder_send(entity to, int sf)
+{SELFPARAM();
WriteHeader(MSG_ENTITY, ENT_CLIENT_LADDER);
WriteString(MSG_ENTITY, self.classname);
WriteByte(MSG_ENTITY, self.skin);
- WriteByte(MSG_ENTITY, self.speed);
- WriteString(MSG_ENTITY, self.mdl);
+ WriteCoord(MSG_ENTITY, self.speed);
- trigger_common_write(false);
+ trigger_common_write(self, false);
return true;
}
void func_ladder_link()
{
- //self.SendEntity = func_ladder_send;
- //self.SendFlags = 0xFFFFFF;
+ self.SendEntity = func_ladder_send;
+ self.SendFlags = 0xFFFFFF;
//self.model = "null";
}
-spawnfunc(func_ladder)
+void func_ladder_init()
{
- self.mdl = self.model;
- EXACTTRIGGER_INIT;
self.touch = func_ladder_touch;
+ trigger_init(self);
func_ladder_link();
}
-spawnfunc(func_water)
+spawnfunc(func_ladder)
{
- self.mdl = self.model;
- EXACTTRIGGER_INIT;
- self.touch = func_ladder_touch;
+ func_ladder_init();
+}
- func_ladder_link();
+spawnfunc(func_water)
+{
+ func_ladder_init();
}
#elif defined(CSQC)
.float speed;
+void func_ladder_remove()
+{
+ if(self.classname) { strunzone(self.classname); }
+ self.classname = string_null;
+}
+
NET_HANDLE(ENT_CLIENT_LADDER, bool isnew)
{
self.classname = strzone(ReadString());
self.skin = ReadByte();
- self.speed = ReadByte();
- self.model = strzone(ReadString());
+ self.speed = ReadCoord();
trigger_common_read(false);
- return = true;
-
- self.mins = self.maxs = '0 0 0';
-
self.solid = SOLID_TRIGGER;
- self.draw = trigger_draw_generic;
- self.trigger_touch = func_ladder_touch;
+ self.move_touch = func_ladder_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
- self.entremove = trigger_remove_generic;
+ self.entremove = func_ladder_remove;
- //precache_model(self.mdl);
- EXACTTRIGGER_INIT;
+ return true;
}
#endif
WriteString(MSG_ENTITY, self.model);
- trigger_common_write(true);
+ trigger_common_write(self, true);
WriteCoord(MSG_ENTITY, self.pos1_x);
WriteCoord(MSG_ENTITY, self.pos1_y);
WriteString(MSG_ENTITY, self.model);
- trigger_common_write(true);
+ trigger_common_write(self, true);
WriteString(MSG_ENTITY, self.curvetarget);
+REGISTER_NET_LINKED(ENT_CLIENT_TELEPORT_DEST)
+
#ifdef SVQC
+bool teleport_dest_send(entity this, entity to, int sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_TELEPORT_DEST);
+ WriteByte(MSG_ENTITY, sf);
+
+ if(sf & 1)
+ {
+ WriteByte(MSG_ENTITY, this.cnt);
+ WriteCoord(MSG_ENTITY, this.speed);
+ WriteString(MSG_ENTITY, this.targetname);
+ WriteCoord(MSG_ENTITY, this.origin_x);
+ WriteCoord(MSG_ENTITY, this.origin_y);
+ WriteCoord(MSG_ENTITY, this.origin_z);
+
+ WriteAngle(MSG_ENTITY, this.mangle_x);
+ WriteAngle(MSG_ENTITY, this.mangle_y);
+ WriteAngle(MSG_ENTITY, this.mangle_z);
+ }
+
+ return true;
+}
+
+void teleport_dest_link()
+{SELFPARAM();
+ Net_LinkEntity(self, false, 0, teleport_dest_send);
+ //self.SendFlags |= 1; // update
+}
+
spawnfunc(info_teleport_destination)
{
self.classname = "info_teleport_destination";
}
else
objerror ("^3Teleport destination without a targetname");
+
+ teleport_dest_link();
}
spawnfunc(misc_teleporter_dest)
spawnfunc_info_teleport_destination(this);
}
+#elif defined(CSQC)
+
+void teleport_dest_remove()
+{SELFPARAM();
+ //if(self.classname)
+ //strunzone(self.classname);
+ //self.classname = string_null;
+
+ if(self.targetname)
+ strunzone(self.targetname);
+ self.targetname = string_null;
+}
+
+NET_HANDLE(ENT_CLIENT_TELEPORT_DEST, bool isnew)
+{
+ int sf = ReadByte();
+
+ if(sf & 1)
+ {
+ self.classname = "info_teleport_destination";
+ self.cnt = ReadByte();
+ self.speed = ReadCoord();
+ self.targetname = strzone(ReadString());
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+
+ self.mangle_x = ReadAngle();
+ self.mangle_y = ReadAngle();
+ self.mangle_z = ReadAngle();
+
+ setorigin(self, self.origin);
+
+ self.drawmask = MASK_NORMAL;
+ self.entremove = teleport_dest_remove;
+ }
+
+ return = true;
+}
+
#endif
.vector destvec;
.vector destvec2;
-// player animation state
-.float animstate_startframe;
-.float animstate_numframes;
-.float animstate_framerate;
-.float animstate_starttime;
-.float animstate_endtime;
-.float animstate_override;
-.float animstate_looping;
-
.float delay;
.float wait;
.float lip;
#include "../../server/anticheat.qh"
#endif
-#ifdef SVQC
-
float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
{
- if (IS_PLAYER(player) && player.health >= 1)
+ if (IS_PLAYER(player) && !PHYS_DEAD(player))
{
TDEATHLOOP(org)
{
+ #ifdef SVQC
if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+ #endif
if(IS_PLAYER(head))
- if(head.health >= 1)
+ if(!PHYS_DEAD(head))
return 1;
}
}
return 0;
}
+#ifdef SVQC
+
+void trigger_teleport_link(entity this);
+
void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
{
TDEATHLOOP(player.origin)
tdeath(e, e, e, '0 0 0', '0 0 0');
}
+#endif
+
void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
{SELFPARAM();
entity telefragger;
makevectors (to_angles);
+#ifdef SVQC
if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
{
if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
self.pushltime = time + 0.2;
}
}
+#endif
// Relocate the player
// assuming to allows PL_MIN to PL_MAX box and some more
+#ifdef SVQC
from = player.origin;
setorigin (player, to);
player.oldorigin = to; // don't undo the teleport by unsticking
makevectors(player.angles);
Reset_ArcBeam(player, v_forward);
UpdateCSQCProjectileAfterTeleport(player);
+#elif defined(CSQC)
+ from = player.move_origin;
+ player.move_origin = to;
+ player.move_angles = to_angles;
+ player.move_velocity = to_velocity;
+ player.move_flags &= ~FL_ONGROUND;
+ player.iflags |= IFLAG_TELEPORTED | IFLAG_V_ANGLE | IFLAG_ANGLES;
+ player.csqcmodel_teleported = 1;
+ player.v_angle = to_angles;
+ setproperty(VF_ANGLES, player.move_angles);
+ setproperty(VF_CL_VIEWANGLES, player.move_angles);
+
+ makevectors(player.move_angles);
+#endif
+#ifdef SVQC
if(IS_PLAYER(player))
{
if(tflags & TELEPORT_FLAG_TDEATH)
player.lastteleporttime = time;
}
+#endif
}
entity Simple_TeleportPlayer(entity teleporter, entity player)
for(e = world; (e = find(e, targetname, teleporter.target)); )
{
p = 1;
- if(autocvar_g_telefrags_avoid)
+ if(STAT(TELEPORT_TELEFRAG_AVOID, player))
{
+ #ifdef SVQC
locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ #elif defined(CSQC)
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ #endif
if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
p = 0;
}
e = RandomSelection_chosen_ent;
}
+#ifdef SVQC
if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+#elif defined(CSQC)
+ if(!e) { LOG_INFO("Teleport destination could not be found from CSQC.\n"); }
+#endif
makevectors(e.mangle);
+#ifdef SVQC
if(e.speed)
if(vlen(player.velocity) > e.speed)
player.velocity = normalize(player.velocity) * max(0, e.speed);
+#elif defined(CSQC)
+ if(e.speed)
+ if(vlen(player.move_velocity) > e.speed)
+ player.move_velocity = normalize(player.move_velocity) * max(0, e.speed);
+#endif
- if(autocvar_g_teleport_maxspeed)
- if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
- player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
+#ifdef SVQC
+ if(STAT(TELEPORT_MAXSPEED, player))
+ if(vlen(player.velocity) > STAT(TELEPORT_MAXSPEED, player))
+ player.velocity = normalize(player.velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#elif defined(CSQC)
+ if(STAT(TELEPORT_MAXSPEED, player))
+ if(vlen(player.move_velocity) > STAT(TELEPORT_MAXSPEED, player))
+ player.move_velocity = normalize(player.move_velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#endif
+#ifdef SVQC
locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#elif defined(CSQC)
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
+ TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.move_velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#endif
return e;
}
-void teleport_findtarget ()
-{SELFPARAM();
+void teleport_findtarget()
+{
+ int n = 0;
entity e;
- float n;
-
- n = 0;
for(e = world; (e = find(e, targetname, self.target)); )
{
++n;
+#ifdef SVQC
if(e.movetype == MOVETYPE_NONE)
waypoint_spawnforteleporter(self, e.origin, 0);
if(e.classname != "info_teleport_destination")
LOG_INFO("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
+#endif
}
if(n == 0)
}
// now enable touch
+#ifdef SVQC
self.touch = Teleport_Touch;
+
+ trigger_teleport_link(self);
+#elif defined(CSQC)
+ self.move_touch = Teleport_Touch;
+#endif
}
entity Teleport_Find(vector mi, vector ma)
void WarpZone_PostTeleportPlayer_Callback(entity pl)
{SELFPARAM();
+#ifdef SVQC
makevectors(pl.angles);
Reset_ArcBeam(pl, v_forward);
UpdateCSQCProjectileAfterTeleport(pl);
{
WITH(entity, self, pl, anticheat_fixangle());
}
+#endif
// "disown" projectiles after teleport
if(pl.owner)
if(pl.owner == pl.realowner)
{
+ #ifdef SVQC
if(!(pl.flags & FL_PROJECTILE))
+ #elif defined(CSQC)
+ if(!(pl.move_flags & BIT(15))) // FL_PROJECTILE
+ #endif
LOG_INFO("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
pl.owner = world;
}
if(IS_PLAYER(pl))
{
// reset tracking of oldvelocity for impact damage (sudden velocity changes)
+ #ifdef SVQC
pl.oldvelocity = pl.velocity;
+ #endif
// reset teleport time tracking too (or multijump can cause insane speeds)
pl.lastteleporttime = time;
}
}
-#endif
#ifndef T_TELEPORTERS_H
#define T_TELEPORTERS_H
+.entity pusher;
+const float TELEPORT_FLAG_SOUND = 1;
+const float TELEPORT_FLAG_PARTICLES = 2;
+const float TELEPORT_FLAG_TDEATH = 4;
+const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+#define TELEPORT_FLAGS_WARPZONE 0
+#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+
+// types for .teleportable entity setting
+const float TELEPORT_NORMAL = 1; // play sounds/effects etc
+const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+
+entity Simple_TeleportPlayer(entity teleporter, entity player);
+
+void Teleport_Touch ();
+
+void teleport_findtarget();
+
+entity Teleport_Find(vector mi, vector ma);
+
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
+
+entity teleport_first;
+.entity teleport_next;
+
#ifdef SVQC
void trigger_teleport_use();
if(head.takedamage) \
if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
-
float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
float tdeath_hit;
void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
void spawn_tdeath(vector v0, entity e, vector v);
-.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
-
-#define TELEPORT_FLAGS_WARPZONE 0
-#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
-#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
-
-// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
-
void Reset_ArcBeam(entity player, vector forward);
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
-
-entity Simple_TeleportPlayer(entity teleporter, entity player);
-
-void Teleport_Touch ();
-void teleport_findtarget ();
+#endif
-entity Teleport_Find(vector mi, vector ma);
+void WarpZone_PostTeleportPlayer_Callback(entity pl);
-entity teleport_first;
-.entity teleport_next;
+#ifdef CSQC
+.entity realowner;
+.float lastteleporttime;
-void WarpZone_PostTeleportPlayer_Callback(entity pl);
+#define TDEATHLOOP(o) \
+ entity head; \
+ vector deathmin; \
+ vector deathmax; \
+ float deathradius; \
+ deathmin = (o) + player.mins; \
+ deathmax = (o) + player.maxs; \
+ if(telefragmin != telefragmax) \
+ { \
+ if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
+ if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
+ if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
+ if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
+ if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
+ if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
+ } \
+ deathradius = max(vlen(deathmin), vlen(deathmax)); \
+ for(head = findradius(o, deathradius); head; head = head.chain) \
+ if(head != player) \
+ if(head.isplayermodel) \
+ if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
#endif
#endif
return;
}
+#ifdef SVQC
str = min(self.radius, vlen(self.origin - other.origin));
+#elif defined(CSQC)
+ str = min(self.radius, vlen(self.origin - other.move_origin));
+#endif
if(self.falloff == 1)
str = (str / self.radius) * self.strength;
if(self.spawnflags & 64)
{
+#ifdef SVQC
float addspeed = str - other.velocity * normalize(targ.origin - self.origin);
if (addspeed > 0)
{
float accelspeed = min(8 * pushdeltatime * str, addspeed);
other.velocity += accelspeed * normalize(targ.origin - self.origin);
}
+#elif defined(CSQC)
+ float addspeed = str - other.move_velocity * normalize(targ.origin - self.origin);
+ if (addspeed > 0)
+ {
+ float accelspeed = min(8 * pushdeltatime * str, addspeed);
+ other.move_velocity += accelspeed * normalize(targ.origin - self.origin);
+ }
+#endif
}
else
+#ifdef SVQC
other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
- other.flags &= ~FL_ONGROUND;
+#elif defined(CSQC)
+ other.move_velocity = other.move_velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
+#endif
+
#ifdef SVQC
+ UNSET_ONGROUND(other);
+
UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+ other.move_flags &= ~FL_ONGROUND;
#endif
}
if(!pushdeltatime) return;
// div0: ticrate independent, 1 = identity (not 20)
- other.velocity = other.velocity * pow(self.strength, pushdeltatime);
#ifdef SVQC
+ other.velocity = other.velocity * pow(self.strength, pushdeltatime);
+
UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+ other.move_velocity = other.move_velocity * pow(self.strength, pushdeltatime);
#endif
}
setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
+#ifdef SVQC
str = min(self.radius, vlen(self.origin - other.origin));
+#elif defined(CSQC)
+ str = min(self.radius, vlen(self.origin - other.move_origin));
+#endif
if(self.falloff == 1)
str = (1 - str / self.radius) * self.strength; // 1 in the inside
else
str = self.strength;
- other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
#ifdef SVQC
+ other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
+
UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+ other.move_velocity = other.move_velocity + normalize(other.move_origin - self.origin) * str * pushdeltatime;
#endif
}
in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
*/
#ifdef SVQC
-bool trigger_impulse_send(entity to, int sf)
-{SELFPARAM();
+bool trigger_impulse_send(entity this, entity to, int sf)
+{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
- WriteCoord(MSG_ENTITY, self.radius);
- WriteCoord(MSG_ENTITY, self.strength);
- WriteByte(MSG_ENTITY, self.falloff);
- WriteByte(MSG_ENTITY, self.active);
+ WriteInt24_t(MSG_ENTITY, this.spawnflags);
+ WriteCoord(MSG_ENTITY, this.radius);
+ WriteCoord(MSG_ENTITY, this.strength);
+ WriteByte(MSG_ENTITY, this.falloff);
+ WriteByte(MSG_ENTITY, this.active);
- trigger_common_write(true);
+ trigger_common_write(this, true);
return true;
}
void trigger_impulse_link()
{
- //Net_LinkEntity(self, 0, false, trigger_impulse_send);
+ trigger_link(self, trigger_impulse_send);
}
spawnfunc(trigger_impulse)
{
self.active = ACTIVE_ACTIVE;
- EXACTTRIGGER_INIT;
+ trigger_init(self);
+
if(self.radius)
{
if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
#elif defined(CSQC)
NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
{
+ self.spawnflags = ReadInt24_t();
self.radius = ReadCoord();
self.strength = ReadCoord();
self.falloff = ReadByte();
self.classname = "trigger_impulse";
self.solid = SOLID_TRIGGER;
self.entremove = trigger_remove_generic;
- self.draw = trigger_draw_generic;
+ //self.draw = trigger_draw_generic;
self.drawmask = MASK_NORMAL;
self.move_time = time;
- if(self.radius) { self.trigger_touch = trigger_impulse_touch3; }
- else if(self.target) { self.trigger_touch = trigger_impulse_touch1; }
- else { self.trigger_touch = trigger_impulse_touch2; }
+ if(self.radius) { self.move_touch = trigger_impulse_touch3; }
+ else if(self.target) { self.move_touch = trigger_impulse_touch1; }
+ else { self.move_touch = trigger_impulse_touch2; }
}
#endif
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
- grav = PHYS_GRAVITY;
+ grav = PHYS_GRAVITY(other);
if(PHYS_ENTGRAVITY(other))
grav *= PHYS_ENTGRAVITY(other);
other.move_velocity = other.velocity;
}
+#ifdef SVQC
UNSET_ONGROUND(other);
-
+#elif defined(CSQC)
other.move_flags &= ~FL_ONGROUND;
+#endif
#ifdef SVQC
if (IS_PLAYER(other))
}
#ifdef SVQC
-float trigger_push_send(entity to, float sf)
-{SELFPARAM();
+float trigger_push_send(entity this, entity to, float sf)
+{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
- WriteByte(MSG_ENTITY, sf);
-
- if(sf & 1)
- {
- WriteByte(MSG_ENTITY, self.team);
- WriteInt24_t(MSG_ENTITY, self.spawnflags);
- WriteByte(MSG_ENTITY, self.active);
- WriteByte(MSG_ENTITY, self.height);
- trigger_common_write(true);
- }
+ WriteByte(MSG_ENTITY, self.team);
+ WriteInt24_t(MSG_ENTITY, self.spawnflags);
+ WriteByte(MSG_ENTITY, self.active);
+ WriteCoord(MSG_ENTITY, self.height);
- if(sf & 2)
- {
- WriteByte(MSG_ENTITY, self.team);
- WriteByte(MSG_ENTITY, self.active);
- }
+ trigger_common_write(self, true);
return true;
}
void trigger_push_link()
{
- //Net_LinkEntity(self, false, 0, trigger_push_send);
+ trigger_link(self, trigger_push_send);
}
-#endif
-#ifdef SVQC
+
/*
* ENTITY PARAMETERS:
*
{
SetMovedir(self);
- EXACTTRIGGER_INIT;
+ trigger_init(self);
self.active = ACTIVE_ACTIVE;
self.use = trigger_push_use;
WriteCoord(MSG_ENTITY, self.origin_y);
WriteCoord(MSG_ENTITY, self.origin_z);
+ WriteAngle(MSG_ENTITY, self.angles_x);
+ WriteAngle(MSG_ENTITY, self.angles_y);
+ WriteAngle(MSG_ENTITY, self.angles_z);
+
return true;
}
void target_push_link()
{SELFPARAM();
- //Net_LinkEntity(self, false, 0, target_push_send);
+ BITSET_ASSIGN(self.effects, EF_NODEPTHTEST);
+ Net_LinkEntity(self, false, 0, target_push_send);
//self.SendFlags |= 1; // update
}
spawnfunc(info_notnull) { target_push_link(); }
spawnfunc(target_position) { make_pure(this); target_push_link(); }
-#endif
-
-#ifdef CSQC
+#elif defined(CSQC)
NET_HANDLE(ENT_CLIENT_TRIGGER_PUSH, bool isnew)
{
- float sf = ReadByte();
+ make_pure(this);
- if(sf & 1)
- {
- self.classname = "jumppad";
- int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
- self.spawnflags = ReadInt24_t();
- self.active = ReadByte();
- self.height = ReadByte();
-
- trigger_common_read(true);
-
- self.entremove = trigger_remove_generic;
- self.solid = SOLID_TRIGGER;
- self.draw = trigger_draw_generic;
- self.trigger_touch = trigger_push_touch;
- self.drawmask = MASK_NORMAL;
- self.move_time = time;
- trigger_push_findtarget();
- }
+ self.classname = "jumppad";
+ int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+ self.spawnflags = ReadInt24_t();
+ self.active = ReadByte();
+ self.height = ReadCoord();
+
+ trigger_common_read(true);
+
+ self.entremove = trigger_remove_generic;
+ self.solid = SOLID_TRIGGER;
+ //self.draw = trigger_draw_generic;
+ self.move_touch = trigger_push_touch;
+ self.drawmask = MASK_NORMAL;
+ self.move_time = time;
+ defer(self, 0.25, trigger_push_findtarget);
- if(sf & 2)
- {
- self.team = ReadByte();
- self.active = ReadByte();
- }
return true;
}
NET_HANDLE(ENT_CLIENT_TARGET_PUSH, bool isnew)
{
+ make_pure(this);
self.classname = "push_target";
self.cnt = ReadByte();
self.targetname = strzone(ReadString());
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ self.angles_x = ReadAngle();
+ self.angles_y = ReadAngle();
+ self.angles_z = ReadAngle();
+
return = true;
setorigin(self, self.origin);
WriteInt24_t(MSG_ENTITY, self.itemkeys);
WriteByte(MSG_ENTITY, self.height);
- trigger_common_write(true);
+ trigger_common_write(self, true);
return true;
}
float secrets_found;
-.float stat_secrets_total;
-.float stat_secrets_found;
+.float stat_secrets_total = _STAT(SECRETS_TOTAL);
+.float stat_secrets_found = _STAT(SECRETS_FOUND);
/**
* update secrets status.
REGISTER_NET_LINKED(ENT_CLIENT_SWAMP)
#ifdef SVQC
-float swamp_send(entity to, float sf)
-{SELFPARAM();
+float swamp_send(entity this, entity to, float sf)
+{
WriteHeader(MSG_ENTITY, ENT_CLIENT_SWAMP);
- WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
- WriteByte(MSG_ENTITY, self.swamp_slowdown);
- WriteByte(MSG_ENTITY, self.swamp_interval);
+ WriteByte(MSG_ENTITY, this.dmg); // can probably get away with using a single byte here
+ WriteByte(MSG_ENTITY, this.swamp_slowdown);
+ WriteByte(MSG_ENTITY, this.swamp_interval);
- trigger_common_write(false);
+ trigger_common_write(this, false);
return true;
}
void swamp_link()
{SELFPARAM();
- Net_LinkEntity(self, false, 0, func_ladder_send);
+ trigger_link(self, swamp_send);
}
/*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
spawnfunc(trigger_swamp)
{
// Init stuff
- EXACTTRIGGER_INIT;
+ trigger_init(self);
self.touch = swamp_touch;
// Setup default keys, if missing
self.classname = "trigger_swamp";
self.solid = SOLID_TRIGGER;
- self.draw = trigger_draw_generic;
- self.trigger_touch = swamp_touch;
+ self.move_touch = swamp_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
self.entremove = trigger_remove_generic;
+REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_TELEPORT)
+
#ifdef SVQC
void trigger_teleport_use()
{SELFPARAM();
self.SendFlags |= SF_TRIGGER_UPDATE;
#endif
}
+#endif
void Teleport_Touch ()
{SELFPARAM();
- string s;
-
if (self.active != ACTIVE_ACTIVE)
return;
+#ifdef SVQC
if (!other.teleportable)
return;
if(IS_TURRET(other))
return;
+#endif
- if(other.deadflag != DEAD_NO)
+ if(PHYS_DEAD(other))
return;
if(self.team)
- if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+ if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(this, other)))
return;
EXACTTRIGGER_TOUCH;
+#ifdef SVQC
if(IS_PLAYER(other))
RemoveGrapplingHook(other);
+#endif
- entity e = Simple_TeleportPlayer(self, other);
+ entity e;
+ e = Simple_TeleportPlayer(self, other);
+#ifdef SVQC
activator = other;
- s = self.target; self.target = string_null;
+ string s = self.target; self.target = string_null;
SUB_UseTargets();
if (!self.target) self.target = s;
WITH(entity, self, e, SUB_UseTargets());
+#endif
+}
+
+#ifdef SVQC
+float trigger_teleport_send(entity this, entity to, float sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_TELEPORT);
+
+ WriteByte(MSG_ENTITY, this.team);
+ WriteInt24_t(MSG_ENTITY, this.spawnflags);
+ WriteByte(MSG_ENTITY, this.active);
+ WriteCoord(MSG_ENTITY, this.speed);
+
+ trigger_common_write(this, true);
+
+ return true;
+}
+
+void trigger_teleport_link(entity this)
+{
+ trigger_link(this, trigger_teleport_send);
}
spawnfunc(trigger_teleport)
{
self.angles = '0 0 0';
- EXACTTRIGGER_INIT;
-
self.active = ACTIVE_ACTIVE;
-
+ trigger_init(self);
self.use = trigger_teleport_use;
// this must be called to spawn the teleport waypoints for bots
self.teleport_next = teleport_first;
teleport_first = self;
}
+#elif defined(CSQC)
+NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
+{
+ self.classname = "trigger_teleport";
+ int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+ self.spawnflags = ReadInt24_t();
+ self.active = ReadByte();
+ self.speed = ReadCoord();
+
+ trigger_common_read(true);
+
+ self.entremove = trigger_remove_generic;
+ self.solid = SOLID_TRIGGER;
+ //self.draw = trigger_draw_generic;
+ //self.move_touch = trigger_push_touch;
+ self.drawmask = MASK_NORMAL;
+ self.move_time = time;
+ defer(self, 0.25, teleport_findtarget);
+
+ self.teleport_next = teleport_first;
+ teleport_first = self;
+
+ return true;
+}
+
#endif
}
#ifdef SVQC
-void trigger_common_write(bool withtarget)
-{SELFPARAM();
- WriteByte(MSG_ENTITY, self.warpzone_isboxy);
- WriteByte(MSG_ENTITY, self.scale);
- if(withtarget)
- {
- WriteString(MSG_ENTITY, self.target);
- WriteString(MSG_ENTITY, self.target2);
- WriteString(MSG_ENTITY, self.target3);
- WriteString(MSG_ENTITY, self.target4);
- WriteString(MSG_ENTITY, self.targetname);
- WriteString(MSG_ENTITY, self.killtarget);
+void trigger_init(entity this)
+{
+ string m = this.model;
+ WITH(entity, self, this, WarpZoneLib_ExactTrigger_Init());
+ if(m != "")
+ {
+ precache_model(m);
+ _setmodel(this, m); // no precision needed
}
+ setorigin(this, this.origin);
+ if(this.scale)
+ setsize(this, this.mins * this.scale, this.maxs * this.scale);
+ else
+ setsize(this, this.mins, this.maxs);
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
+ BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
+}
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
+void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
+{
+ this.SendEntity = SendEntity_self;
+ this.SendEntity3 = sendfunc;
+ this.SendFlags = 0xFFFFFF;
+}
- WriteCoord(MSG_ENTITY, self.movedir_x);
- WriteCoord(MSG_ENTITY, self.movedir_y);
- WriteCoord(MSG_ENTITY, self.movedir_z);
+void trigger_common_write(entity this, bool withtarget)
+{
+ int f = 0;
+ if(this.warpzone_isboxy)
+ BITSET_ASSIGN(f, 1);
+ if(this.origin != '0 0 0')
+ BITSET_ASSIGN(f, 4);
+ WriteByte(MSG_ENTITY, f);
- WriteCoord(MSG_ENTITY, self.angles_x);
- WriteCoord(MSG_ENTITY, self.angles_y);
- WriteCoord(MSG_ENTITY, self.angles_z);
+ if(withtarget)
+ {
+ WriteString(MSG_ENTITY, this.target);
+ WriteString(MSG_ENTITY, this.target2);
+ WriteString(MSG_ENTITY, this.target3);
+ WriteString(MSG_ENTITY, this.target4);
+ WriteString(MSG_ENTITY, this.targetname);
+ WriteString(MSG_ENTITY, this.killtarget);
+ }
+
+ if(f & 4)
+ {
+ WriteCoord(MSG_ENTITY, this.origin.x);
+ WriteCoord(MSG_ENTITY, this.origin.y);
+ WriteCoord(MSG_ENTITY, this.origin.z);
+ }
+
+ WriteShort(MSG_ENTITY, this.modelindex);
+ WriteCoord(MSG_ENTITY, this.mins.x);
+ WriteCoord(MSG_ENTITY, this.mins.y);
+ WriteCoord(MSG_ENTITY, this.mins.z);
+ WriteCoord(MSG_ENTITY, this.maxs.x);
+ WriteCoord(MSG_ENTITY, this.maxs.y);
+ WriteCoord(MSG_ENTITY, this.maxs.z);
+ WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
+
+ WriteCoord(MSG_ENTITY, this.movedir_x);
+ WriteCoord(MSG_ENTITY, this.movedir_y);
+ WriteCoord(MSG_ENTITY, this.movedir_z);
+
+ WriteCoord(MSG_ENTITY, this.angles_x);
+ WriteCoord(MSG_ENTITY, this.angles_y);
+ WriteCoord(MSG_ENTITY, this.angles_z);
}
#elif defined(CSQC)
void trigger_common_read(bool withtarget)
{SELFPARAM();
- self.warpzone_isboxy = ReadByte();
- self.scale = ReadByte();
+ int f = ReadByte();
+ self.warpzone_isboxy = (f & 1);
if(withtarget)
{
+ if(self.target) { strunzone(self.target); }
self.target = strzone(ReadString());
+ if(self.target2) { strunzone(self.target2); }
self.target2 = strzone(ReadString());
+ if(self.target3) { strunzone(self.target3); }
self.target3 = strzone(ReadString());
+ if(self.target4) { strunzone(self.target4); }
self.target4 = strzone(ReadString());
+ if(self.targetname) { strunzone(self.targetname); }
self.targetname = strzone(ReadString());
+ if(self.killtarget) { strunzone(self.killtarget); }
self.killtarget = strzone(ReadString());
}
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
+ if(f & 4)
+ {
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ }
+ else
+ self.origin = '0 0 0';
setorigin(self, self.origin);
+ self.modelindex = ReadShort();
self.mins_x = ReadCoord();
self.mins_y = ReadCoord();
self.mins_z = ReadCoord();
self.maxs_x = ReadCoord();
self.maxs_y = ReadCoord();
self.maxs_z = ReadCoord();
+ self.scale = ReadByte() / 16;
setsize(self, self.mins, self.maxs);
self.movedir_x = ReadCoord();
// used elsewhere (will fix)
#ifdef SVQC
-void trigger_common_write(bool withtarget);
+void trigger_common_write(entity this, bool withtarget);
string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
return;
float dist = vlen(self.origin - view_origin);
- float t = (GetPlayerColor(player_localnum) + 1);
+ float t = (entcs_GetTeam(player_localnum) + 1);
vector o;
string txt;
#include "all.qh"
-#ifndef MENUQC
-STATIC_INIT(vehicles_common_initialize)
-{
-#ifdef SVQC
- addstat(STAT_HUD, AS_INT, hud);
- addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health);
- addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield);
- addstat(STAT_VEHICLESTAT_ENERGY, AS_INT, vehicle_energy);
-
- addstat(STAT_VEHICLESTAT_W2MODE, AS_INT, vehicle_weapon2mode);
-
- addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1);
- addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
-
- addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2);
- addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
-#endif // SVQC
-}
-#endif
-
REGISTER_NET_LINKED(ENT_CLIENT_AUXILIARYXHAIR)
#if defined(SVQC)
float barAlpha = autocvar_hud_progressbar_alpha * hudAlpha;
float blinkValue = 0.55 + sin(time * 7) * 0.45;
- float health = getstati(STAT_VEHICLESTAT_HEALTH) * 0.01;
- float shield = getstati(STAT_VEHICLESTAT_SHIELD) * 0.01;
- float energy = getstati(STAT_VEHICLESTAT_ENERGY) * 0.01;
- float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1) * 0.01;
- float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01;
- float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2) * 0.01;
- float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+ float health = STAT(VEHICLESTAT_HEALTH) * 0.01;
+ float shield = STAT(VEHICLESTAT_SHIELD) * 0.01;
+ float energy = STAT(VEHICLESTAT_ENERGY) * 0.01;
+ float ammo1 = STAT(VEHICLESTAT_AMMO1) * 0.01;
+ float reload1 = STAT(VEHICLESTAT_RELOAD1) * 0.01;
+ float ammo2 = STAT(VEHICLESTAT_AMMO2) * 0.01;
+ float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
// HACK to deal with the inconsistent use of the vehicle stats
ammo1 = (ammo1) ? ammo1 : energy;
void RaptorCBShellfragDraw(entity this);
void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
-#define weapon2mode getstati(STAT_VEHICLESTAT_W2MODE)
+#define weapon2mode STAT(VEHICLESTAT_W2MODE)
#endif
vehicles_enter(other, self);
}
-bool vehicle_impulse(int imp)
-{SELFPARAM();
- switch(imp)
+bool vehicle_impulse(entity this, int imp)
+{
+ entity v = this.vehicle;
+ if (!v) return false;
+ if (v.deadflag != DEAD_NO) return false;
+ bool(int) f = v.vehicles_impulse;
+ if (f && f(imp)) return true;
+ switch (imp)
{
- case 17:
+ case IMP_weapon_drop.impulse:
{
stuffcmd(self, "\ntoggle cl_eventchase_vehicle\nset _vehicles_shownchasemessage 1\n");
return true;
}
}
-
return false;
}
.entity gunner1;
.entity gunner2;
-.float vehicle_health; /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
-.float vehicle_energy; /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
-.float vehicle_shield; /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
+.float vehicle_health = _STAT(VEHICLESTAT_HEALTH); /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
+.float vehicle_energy = _STAT(VEHICLESTAT_ENERGY); /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
+.float vehicle_shield = _STAT(VEHICLESTAT_SHIELD); /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
-.float vehicle_ammo1; /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
-.float vehicle_reload1; /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
-.float vehicle_ammo2; /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
-.float vehicle_reload2; /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
+.float vehicle_ammo1 = _STAT(VEHICLESTAT_AMMO1); /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
+.float vehicle_reload1 = _STAT(VEHICLESTAT_RELOAD1); /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
+.float vehicle_ammo2 = _STAT(VEHICLESTAT_AMMO2); /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
+.float vehicle_reload2 = _STAT(VEHICLESTAT_RELOAD2); /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
.float sound_nexttime;
const float VOL_VEHICLEENGINE = 1;
const float VHSF_NORMAL = 0;
const float VHSF_FACTORY = 2;
-.int hud;
+.int hud = _STAT(HUD);
.float dmg_time;
.int volly_counter;
// vehicle functions
.void(int _spawnflag) vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
.bool(int _imp) vehicles_impulse;
-.int vehicle_weapon2mode;
+.int vehicle_weapon2mode = _STAT(VEHICLESTAT_W2MODE);
.void(int exit_flags) vehicle_exit;
.bool() vehicle_enter;
const int VHEF_NORMAL = 0; /// User pressed exit key
void vehicles_exit(float eject);
float vehicle_initialize(entity vehicle, float nodrop);
-bool vehicle_impulse(int imp);
+bool vehicle_impulse(entity this, int imp);
bool vehicles_crushable(entity e);
#endif
{SELFPARAM();
switch(_imp)
{
- case 1:
+ case IMP_weapon_group_1.impulse:
self.vehicle.vehicle_weapon2mode = RSM_BOMB;
CSQCVehicleSetup(self, 0);
return true;
- case 2:
+ case IMP_weapon_group_2.impulse:
self.vehicle.vehicle_weapon2mode = RSM_FLARE;
CSQCVehicleSetup(self, 0);
return true;
- case 10:
- case 15:
- case 18:
+ case IMP_weapon_next_byid.impulse:
+ case IMP_weapon_next_bypriority.impulse:
+ case IMP_weapon_next_bygroup.impulse:
self.vehicle.vehicle_weapon2mode += 1;
if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
self.vehicle.vehicle_weapon2mode = RSM_FIRST;
CSQCVehicleSetup(self, 0);
return true;
- case 11:
- case 12:
- case 16:
- case 19:
+ case IMP_weapon_last.impulse:
+ case IMP_weapon_prev_byid.impulse:
+ case IMP_weapon_prev_bypriority.impulse:
+ case IMP_weapon_prev_bygroup.impulse:
self.vehicle.vehicle_weapon2mode -= 1;
if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
self.vehicle.vehicle_weapon2mode = RSM_LAST;
return true;
/*
- case 17: // toss gun, could be used to exit?
+ case IMP_weapon_drop.impulse: // toss gun, could be used to exit?
break;
- case 20: // Manual minigun reload?
+ case IMP_weapon_reload.impulse: // Manual minigun reload?
break;
*/
}
dropmark.gravity = 1;
}
- float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+ float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
if(reload2 == 1)
{
setorigin(dropmark, pmove_org);
{SELFPARAM();
switch(_imp)
{
- case 1:
+ case IMP_weapon_group_1.impulse:
self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
CSQCVehicleSetup(self, 0);
return true;
- case 2:
+ case IMP_weapon_group_2.impulse:
self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
CSQCVehicleSetup(self, 0);
return true;
- case 3:
+ case IMP_weapon_group_3.impulse:
self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
CSQCVehicleSetup(self, 0);
return true;
- case 10:
- case 15:
- case 18:
+ case IMP_weapon_next_byid.impulse:
+ case IMP_weapon_next_bypriority.impulse:
+ case IMP_weapon_next_bygroup.impulse:
self.vehicle.vehicle_weapon2mode += 1;
if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
//centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
CSQCVehicleSetup(self, 0);
return true;
- case 11:
- case 12:
- case 16:
- case 19:
+ case IMP_weapon_last.impulse:
+ case IMP_weapon_prev_byid.impulse:
+ case IMP_weapon_prev_bypriority.impulse:
+ case IMP_weapon_prev_bygroup.impulse:
self.vehicle.vehicle_weapon2mode -= 1;
if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
self.vehicle.vehicle_weapon2mode = SBRM_LAST;
return true;
/*
- case 17: // toss gun, could be used to exit?
+ case IMP_weapon_drop.impulse: // toss gun, could be used to exit?
break;
- case 20: // Manual minigun reload?
+ case IMP_weapon_reload.impulse: // Manual minigun reload?
break;
*/
}
#include "../../server/g_hook.qh"
#endif
#ifndef MENUQC
-#include "calculations.qc"
+ #include "calculations.qc"
#endif
#define IMPLEMENTATION
#include "all.inc"
// WEAPON PLUGIN SYSTEM
-WepSet _WepSet_FromWeapon(int a) {
+WepSet _WepSet_FromWeapon(int a)
+{
a -= WEP_FIRST;
if (Weapons_MAX > 24)
- if (a >= 24) {
- a -= 24;
- if (Weapons_MAX > 48)
- if (a >= 24) {
+ if (a >= 24)
+ {
a -= 24;
- return '0 0 1' * power2of(a);
+ if (Weapons_MAX > 48)
+ if (a >= 24)
+ {
+ a -= 24;
+ return '0 0 1' * power2of(a);
+ }
+ return '0 1 0' * power2of(a);
}
- return '0 1 0' * power2of(a);
- }
return '1 0 0' * power2of(a);
}
#ifdef SVQC
-void WepSet_AddStat()
-{
- addstat(STAT_WEAPONS, AS_INT, weapons_x);
- if (Weapons_MAX > 24)
- addstat(STAT_WEAPONS2, AS_INT, weapons_y);
- if (Weapons_MAX > 48)
- addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-}
-void WepSet_AddStat_InMap()
-{
- addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
- if (Weapons_MAX > 24)
- addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
- if (Weapons_MAX > 48)
- addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
-}
-void WriteWepSet(float dst, WepSet w)
-{
- if (Weapons_MAX > 48)
- WriteInt72_t(dst, w);
- else if (Weapons_MAX > 24)
- WriteInt48_t(dst, w);
- else
- WriteInt24_t(dst, w.x);
-}
+ void WriteWepSet(float dst, WepSet w)
+ {
+ if (Weapons_MAX > 48) WriteInt72_t(dst, w);
+ else if (Weapons_MAX > 24) WriteInt48_t(dst, w);
+ else WriteInt24_t(dst, w.x);
+ }
#endif
#ifdef CSQC
-WepSet WepSet_GetFromStat()
-{
- WepSet w = '0 0 0';
- w.x = getstati(STAT_WEAPONS);
- if (Weapons_MAX > 24)
- w.y = getstati(STAT_WEAPONS2);
- if (Weapons_MAX > 48)
- w.z = getstati(STAT_WEAPONS3);
- return w;
-}
-WepSet WepSet_GetFromStat_InMap()
-{
- WepSet w = '0 0 0';
- w_x = getstati(STAT_WEAPONSINMAP);
- if (Weapons_MAX > 24)
- w_y = getstati(STAT_WEAPONSINMAP2);
- if (Weapons_MAX > 48)
- w_z = getstati(STAT_WEAPONSINMAP3);
- return w;
-}
-WepSet ReadWepSet()
-{
- if (Weapons_MAX > 48)
- return ReadInt72_t();
- if (Weapons_MAX > 24)
- return ReadInt48_t();
- return ReadInt24_t() * '1 0 0';
-}
+ WepSet WepSet_GetFromStat()
+ {
+ return STAT(WEAPONS);
+ }
+ WepSet WepSet_GetFromStat_InMap()
+ {
+ return STAT(WEAPONSINMAP);
+ }
+ WepSet ReadWepSet()
+ {
+ if (Weapons_MAX > 48) return ReadInt72_t();
+ if (Weapons_MAX > 24) return ReadInt48_t();
+ return ReadInt24_t() * '1 0 0';
+ }
#endif
string W_FixWeaponOrder(string order, float complete)
}
string W_NameWeaponOrder_MapFunc(string s)
{
- entity wi;
- if(s == "0" || stof(s))
+ int i = stof(s);
+ if (s == "0" || i)
{
- wi = get_weaponinfo(stof(s));
- if(wi != WEP_Null)
- return wi.netname;
+ entity wi = Weapons_from(i);
+ if (wi != WEP_Null) return wi.netname;
}
return s;
}
string W_UndeprecateName(string s)
{
- switch ( s )
+ switch (s)
{
- case "nex" : return "vortex";
- case "rocketlauncher" : return "devastator";
- case "laser" : return "blaster";
- case "minstanex" : return "vaporizer";
+ case "nex": return "vortex";
+ case "rocketlauncher": return "devastator";
+ case "laser": return "blaster";
+ case "minstanex": return "vaporizer";
case "grenadelauncher": return "mortar";
- case "uzi" : return "machinegun";
- default : return s;
+ case "uzi": return "machinegun";
+ default: return s;
}
}
string W_NameWeaponOrder(string order)
}
string W_NumberWeaponOrder_MapFunc(string s)
{
- int i;
- if(s == "0" || stof(s))
- return s;
+ if (s == "0" || stof(s)) return s;
s = W_UndeprecateName(s);
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- if(s == get_weaponinfo(i).netname)
- return ftos(i);
+ FOREACH(Weapons, it != WEP_Null && it.netname == s, LAMBDA(return ftos(i)));
return s;
}
string W_NumberWeaponOrder(string order)
}
float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
{
- entity e1, e2;
- float d;
- e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
- e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
- d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
- if(d != 0)
- return -d; // high impulse first!
- return
- strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
- -
- strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
- ; // low char index first!
+ int si = W_FixWeaponOrder_BuildImpulseList_buf[i];
+ Weapon e1 = Weapons_from(si);
+ int sj = W_FixWeaponOrder_BuildImpulseList_buf[j];
+ Weapon e2 = Weapons_from(sj);
+ int d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
+ if (d != 0) return -d; // high impulse first!
+ return strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
+ sprintf(" %d ", si), 0)
+ -
+ strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
+ sprintf(" %d ", sj), 0)
+ ; // low char index first!
}
string W_FixWeaponOrder_BuildImpulseList(string o)
{
int i;
W_FixWeaponOrder_BuildImpulseList_order = o;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ for (i = WEP_FIRST; i <= WEP_LAST; ++i)
W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
- heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
+ heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp,
+ world);
o = "";
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ for (i = WEP_FIRST; i <= WEP_LAST; ++i)
o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
W_FixWeaponOrder_BuildImpulseList_order = string_null;
return substring(o, 1, -1);
string W_FixWeaponOrder_ForceComplete(string order)
{
- if(order == "")
- order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
+ if (order == "") order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
return W_FixWeaponOrder(order, 1);
}
WepSet result;
remaining = e.weapons;
result = '0 0 0';
- for(i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i)
{
RandomSelection_Init();
- for(j = WEP_FIRST; j <= WEP_LAST; ++j)
- if(remaining & WepSet_FromWeapon(j))
- RandomSelection_Add(world, j, string_null, 1, 1);
- result |= WepSet_FromWeapon(RandomSelection_chosen_float);
- remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
+ for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+ if (remaining & WepSet_FromWeapon(Weapons_from(j))) RandomSelection_Add(NULL, j, string_null, 1, 1);
+ Weapon w = Weapons_from(RandomSelection_chosen_float);
+ result |= WepSet_FromWeapon(w);
+ remaining &= ~WepSet_FromWeapon(w);
}
e.weapons = result;
}
case ammo_cells: return ITEM_Cells.m_icon;
case ammo_plasma: return ITEM_Plasma.m_icon;
case ammo_fuel: return ITEM_JetpackFuel.m_icon;
- default: return ""; // wtf, no ammo type?
+ default: return ""; // wtf, no ammo type?
}
}
#ifdef CSQC
-.int GetAmmoFieldFromNum(int i)
-{
- switch(i)
+ .int GetAmmoFieldFromNum(int i)
{
- case 0: return ammo_shells;
- case 1: return ammo_nails;
- case 2: return ammo_rockets;
- case 3: return ammo_cells;
- case 4: return ammo_plasma;
- case 5: return ammo_fuel;
- default: return ammo_none;
+ switch (i)
+ {
+ case 0: return ammo_shells;
+ case 1: return ammo_nails;
+ case 2: return ammo_rockets;
+ case 3: return ammo_cells;
+ case 4: return ammo_plasma;
+ case 5: return ammo_fuel;
+ default: return ammo_none;
+ }
}
-}
-int GetAmmoStat(.int ammotype)
-{
- switch(ammotype)
+ int GetAmmoStat(.int ammotype)
{
- case ammo_shells: return STAT_SHELLS;
- case ammo_nails: return STAT_NAILS;
- case ammo_rockets: return STAT_ROCKETS;
- case ammo_cells: return STAT_CELLS;
- case ammo_plasma: return STAT_PLASMA;
- case ammo_fuel: return STAT_FUEL;
- default: return -1;
+ switch (ammotype)
+ {
+ case ammo_shells: return STAT_SHELLS;
+ case ammo_nails: return STAT_NAILS;
+ case ammo_rockets: return STAT_ROCKETS;
+ case ammo_cells: return STAT_CELLS;
+ case ammo_plasma: return STAT_PLASMA.m_id;
+ case ammo_fuel: return STAT_FUEL.m_id;
+ default: return -1;
+ }
}
-}
#endif
string W_Sound(string w_snd)
{
string output = strcat("weapons/", w_snd);
#ifdef SVQC
- MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
- return weapon_sound_output;
+ MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
+ return weapon_sound_output;
#else
- return output;
+ return output;
#endif
}
string W_Model(string w_mdl)
{
string output = strcat("models/weapons/", w_mdl);
-#ifdef SVQC
MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
return weapon_model_output;
+}
+
+#ifndef MENUQC
+vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
+{
+ switch (algn)
+ {
+ default:
+ case 3:
+ // right alignment
+ break;
+ case 4:
+ // left
+ vecs.y = -vecs.y;
+ break;
+ case 1:
+ case 2:
+ // center
+ vecs.y = 0;
+ vecs.z -= 2;
+ break;
+ }
+ return vecs;
+}
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
+{
+#ifdef SVQC
+ string s;
+#endif
+ if (visual)
+ {
+ vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
+ }
+#ifdef SVQC
+ else if (autocvar_g_shootfromeye)
+ {
+ vecs.y = vecs.z = 0;
+ }
+ else if (autocvar_g_shootfromcenter)
+ {
+ vecs.y = 0;
+ vecs.z -= 2;
+ }
+ else if ((s = autocvar_g_shootfromfixedorigin) != "")
+ {
+ vector v = stov(s);
+ if (y_is_right) v.y = -v.y;
+ if (v.x != 0) vecs.x = v.x;
+ vecs.y = v.y;
+ vecs.z = v.z;
+ }
+#endif
+ else // just do the same as top
+ {
+ vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
+ }
+
+ return vecs;
+}
+
+#define shotorg_adjust shotorg_adjust_values
+
+/**
+ * supported formats:
+ *
+ * 1. simple animated model, muzzle flash handling on h_ model:
+ * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ * tags:
+ * shot = muzzle end (shot origin, also used for muzzle flashes)
+ * shell = casings ejection point (must be on the right hand side of the gun)
+ * weapon = attachment for v_tuba.md3
+ * v_tuba.md3 - first and third person model
+ * g_tuba.md3 - pickup model
+ *
+ * 2. simple animated model, muzzle flash handling on v_ model:
+ * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ * tags:
+ * weapon = attachment for v_tuba.md3
+ * v_tuba.md3 - first and third person model
+ * tags:
+ * shot = muzzle end (shot origin, also used for muzzle flashes)
+ * shell = casings ejection point (must be on the right hand side of the gun)
+ * g_tuba.md3 - pickup model
+ *
+ * 3. fully animated model, muzzle flash handling on h_ model:
+ * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ * tags:
+ * shot = muzzle end (shot origin, also used for muzzle flashes)
+ * shell = casings ejection point (must be on the right hand side of the gun)
+ * handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
+ * v_tuba.md3 - third person model
+ * g_tuba.md3 - pickup model
+ *
+ * 4. fully animated model, muzzle flash handling on v_ model:
+ * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ * tags:
+ * shot = muzzle end (shot origin)
+ * shell = casings ejection point (must be on the right hand side of the gun)
+ * v_tuba.md3 - third person model
+ * tags:
+ * shot = muzzle end (for muzzle flashes)
+ * g_tuba.md3 - pickup model
+ *
+ * writes:
+ * this.origin, this.angles
+ * this.weaponchild
+ * this.movedir, this.view_ofs
+ * attachment stuff
+ * anim stuff
+ * to free:
+ * call again with ""
+ * remove the ent
+ */
+void CL_WeaponEntity_SetModel(entity this, string name)
+{
+ if (name == "")
+ {
+ this.model = "";
+ if (this.weaponchild) remove(this.weaponchild);
+ this.weaponchild = NULL;
+ this.movedir = '0 0 0';
+ this.spawnorigin = '0 0 0';
+ this.oldorigin = '0 0 0';
+ this.anim_fire1 = '0 1 0.01';
+ this.anim_fire2 = '0 1 0.01';
+ this.anim_idle = '0 1 0.01';
+ this.anim_reload = '0 1 0.01';
+ }
+ else
+ {
+ // if there is a child entity, hide it until we're sure we use it
+ if (this.weaponchild) this.weaponchild.model = "";
+ _setmodel(this, W_Model(strcat("v_", name, ".md3")));
+ int v_shot_idx; // used later
+ (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot"));
+
+ _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
+ // preset some defaults that work great for renamed zym files (which don't need an animinfo)
+ this.anim_fire1 = animfixfps(this, '0 1 0.01', '0 0 0');
+ this.anim_fire2 = animfixfps(this, '1 1 0.01', '0 0 0');
+ this.anim_idle = animfixfps(this, '2 1 0.01', '0 0 0');
+ this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
+
+ // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
+ // if we don't, this is a "real" animated model
+ string t;
+ if ((t = "weapon", gettagindex(this, t)) || (t = "tag_weapon", gettagindex(this, t)))
+ {
+ if (!this.weaponchild)
+ {
+ this.weaponchild = new(weaponchild);
+ make_pure(this.weaponchild);
+#ifdef CSQC
+ this.weaponchild.drawmask = MASK_NORMAL;
+ this.weaponchild.renderflags |= RF_VIEWMODEL;
+#endif
+ }
+ _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3")));
+ setattachment(this.weaponchild, this, t);
+ }
+ else
+ {
+ if (this.weaponchild) remove(this.weaponchild);
+ this.weaponchild = NULL;
+ }
+
+ setorigin(this, '0 0 0');
+ this.angles = '0 0 0';
+ this.frame = 0;
+#ifdef SVQC
+ this.viewmodelforclient = NULL;
+#else
+ this.renderflags &= ~RF_VIEWMODEL;
+#endif
+ if (v_shot_idx) // v_ model attached to invisible h_ model
+ {
+ this.movedir = gettaginfo(this.weaponchild, v_shot_idx);
+ }
+ else
+ {
+ int idx;
+ if ((idx = gettagindex(this, "shot")) || (idx = gettagindex(this, "tag_shot")))
+ {
+ this.movedir = gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n",
+ this.model);
+ this.movedir = '0 0 0';
+ }
+ }
+ {
+ int idx = 0;
+ // v_ model attached to invisible h_ model
+ if (this.weaponchild
+ && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell"))))
+ {
+ this.spawnorigin = gettaginfo(this.weaponchild, idx);
+ }
+ else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell")))
+ {
+ this.spawnorigin = gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n",
+ this.model);
+ this.spawnorigin = this.movedir;
+ }
+ }
+ if (v_shot_idx)
+ {
+ this.oldorigin = '0 0 0'; // use regular attachment
+ }
+ else
+ {
+ int idx;
+ if (this.weaponchild)
+ (idx = gettagindex(this, "weapon")) || (idx = gettagindex(this, "tag_weapon"));
+ else
+ (idx = gettagindex(this, "handle")) || (idx = gettagindex(this, "tag_handle"));
+ if (idx)
+ {
+ this.oldorigin = this.movedir - gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF(
+ "weapon model %s does not support the 'handle' tag "
+ "and neither does the v_ model support the 'shot' tag, "
+ "will display muzzle flashes TOTALLY wrong\n",
+ this.model);
+ this.oldorigin = '0 0 0'; // there is no way to recover from this
+ }
+ }
+
+#ifdef SVQC
+ this.viewmodelforclient = this.owner;
+#else
+ this.renderflags |= RF_VIEWMODEL;
+#endif
+ }
+
+ this.view_ofs = '0 0 0';
+
+ if (this.movedir.x >= 0)
+ {
+#ifdef SVQC
+ int algn = this.owner.cvar_cl_gunalign;
+#else
+ int algn = autocvar_cl_gunalign;
+#endif
+ vector v = this.movedir;
+ this.movedir = shotorg_adjust(v, false, false, algn);
+ this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
+ }
+ int compressed_shotorg = compressShotOrigin(this.movedir);
+ // make them match perfectly
+#ifdef SVQC
+ this.movedir = decompressShotOrigin(this.owner.stat_shotorg = compressed_shotorg);
#else
- return output;
+ this.movedir = decompressShotOrigin(compressed_shotorg);
#endif
+
+ this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount
+
+ // check if an instant weapon switch occurred
+ setorigin(this, this.view_ofs);
+ // reset animstate now
+ this.wframe = WFRAME_IDLE;
+ setanim(this, this.anim_idle, true, false, true);
}
+#endif
+
+#ifndef MENUQC
+
+REGISTER_NET_TEMP(wframe)
+#ifdef CSQC
+NET_HANDLE(wframe, bool isNew)
+{
+ vector a;
+ a.x = ReadCoord();
+ a.y = ReadCoord();
+ a.z = ReadCoord();
+ bool restartanim = ReadByte();
+ anim_set(viewmodel, a, !restartanim, restartanim, restartanim);
+ viewmodel.state = ReadByte();
+ viewmodel.weapon_nextthink = ReadFloat();
+ viewmodel.alpha = ReadByte() / 255;
+ switch (viewmodel.state)
+ {
+ case WS_RAISE:
+ case WS_DROP:
+ viewmodel.weapon_switchdelay = ReadFloat();
+ break;
+ default:
+ viewmodel.weapon_switchdelay = 0;
+ break;
+ }
+ return true;
+}
+#endif
+
+#ifdef SVQC
+void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
+{
+ if (!IS_REAL_CLIENT(actor)) return;
+ int channel = MSG_ONE;
+ msg_entity = actor;
+ WriteHeader(channel, wframe);
+ WriteCoord(channel, a.x);
+ WriteCoord(channel, a.y);
+ WriteCoord(channel, a.z);
+ WriteByte(channel, restartanim);
+ WriteByte(channel, weaponentity.state);
+ WriteFloat(channel, weaponentity.weapon_nextthink);
+ WriteByte(channel, weaponentity.m_alpha * 255);
+ Weapon w = Weapons_from(actor.weapon);
+ switch (weaponentity.state)
+ {
+ case WS_RAISE:
+ WriteFloat(channel, w.switchdelay_raise);
+ break;
+ case WS_DROP:
+ WriteFloat(channel, w.switchdelay_drop);
+ break;
+ }
+}
+#endif
+
+#endif
#endif
// weapon sets
typedef vector WepSet;
#ifdef SVQC
-void WepSet_AddStat();
-void WepSet_AddStat_InMap();
void WriteWepSet(float dest, WepSet w);
#endif
REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
#define Weapons_from(i) _Weapons_from(i, WEP_Null)
-#define get_weaponinfo(i) Weapons_from(i)
REGISTER_REGISTRY(Weapons)
STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, LAMBDA(it.m_pickup = NEW(WeaponPickup, it))); }
.WepSet m_wepset;
#define WEPSET(id) (WEP_##id.m_wepset)
-#define WepSet_FromWeapon(i) (Weapons_from(i).m_wepset)
+#define WepSet_FromWeapon(it) ((it).m_wepset)
WepSet _WepSet_FromWeapon(int i);
STATIC_INIT(WepSets)
{
if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
it.weapon = it.m_id;
it.weapons = set;
+ if (it == WEP_Null) continue;
int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
if (imp <= WEP_IMPULSE_END)
localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
else
- LOG_TRACEF(_("Impulse limit exceeded, weapon will not be directly accessible: %s\n"), it.netname);
+ LOG_TRACEF("Impulse limit exceeded, weapon will not be directly accessible: %s\n", it.netname);
));
#ifdef CSQC
FOREACH(Weapons, true, LAMBDA(it.wr_init(it)));
for (int i = Weapons_MAX - 1; i >= 1; --i)
if (Weapons_from(i))
weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
- weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+ weaponorder_byid = strzone(substring(weaponorder_byid, 1, -1));
}
+#ifndef MENUQC
+
+.entity weaponchild;
+.entity exteriorweaponentity;
+.vector weaponentity_glowmod;
+
+//.int weapon; // current weapon
+#ifdef SVQC
+.int switchweapon = _STAT(SWITCHWEAPON);
+.int switchingweapon = _STAT(SWITCHINGWEAPON);
+#endif
+.string weaponname; // name of .weapon
+
+.vector spawnorigin; // for casings
+
+// weapon animation vectors:
+.vector anim_fire1;
+.vector anim_fire2;
+.vector anim_idle;
+.vector anim_reload;
+
+// static frame globals
+
+ENUMCLASS(WFRAME)
+CASE(WFRAME, DONTCHANGE)
+CASE(WFRAME, FIRE1)
+CASE(WFRAME, FIRE2)
+CASE(WFRAME, IDLE)
+CASE(WFRAME, RELOAD)
+ENUMCLASS_END(WFRAME)
+
+.WFRAME wframe;
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
+void CL_WeaponEntity_SetModel(entity this, string name);
+#endif
+
#endif
void Dump_Weapon_Settings()
{
- int i, x, totalsettings = 0;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
+ int totalweapons = 0, totalsettings = 0;
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
// step 1: clear the queue
WEP_CONFIG_COUNT = 0;
- for(x = 0; x <= MAX_WEP_CONFIG; ++x)
+ for (int x = 0; x <= MAX_WEP_CONFIG; ++x)
{ wep_config_queue[x] = string_null; }
// step 2: build new queue
- Weapon w = get_weaponinfo(i);
- w.wr_config(w);
+ it.wr_config(it);
// step 3: sort queue
heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world);
WEP_CONFIG_WRITETOFILE(sprintf(
"// {{{ #%d: %s%s\n",
i,
- WEP_NAME(i),
- (((get_weaponinfo(i)).spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
+ it.m_name,
+ ((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
));
- for(x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]); }
+ for (int x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]); }
WEP_CONFIG_WRITETOFILE("// }}}\n");
// step 5: debug info
- LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, WEP_NAME(i), WEP_CONFIG_COUNT));
+ LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, it.m_name, WEP_CONFIG_COUNT));
+ totalweapons += 1;
totalsettings += WEP_CONFIG_COUNT;
- }
+ ));
// clear queue now that we're finished
WEP_CONFIG_COUNT = 0;
- for(x = 0; x <= MAX_WEP_CONFIG; ++x)
+ for(int x = 0; x <= MAX_WEP_CONFIG; ++x)
{ wep_config_queue[x] = string_null; }
// extra information
- LOG_INFO(sprintf("Totals: %d weapons, %d settings\n", (i - 1), totalsettings));
+ LOG_INFO(sprintf("Totals: %d weapons, %d settings\n", totalweapons, totalsettings));
}
#ifndef WEAPON_H
#define WEAPON_H
#include "../items/item/pickup.qh"
+#include "../stats.qh"
const int MAX_WEAPONSLOTS = 2;
.entity weaponentities[MAX_WEAPONSLOTS];
return 0;
}
+// weapon states (actor.(weaponentity).state)
+/** no weapon selected */
+const int WS_CLEAR = 0;
+/** raise frame */
+const int WS_RAISE = 1;
+/** deselecting frame */
+const int WS_DROP = 2;
+/** fire state */
+const int WS_INUSE = 3;
+/** idle frame */
+const int WS_READY = 4;
+
+#ifdef SVQC
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma = _STAT(PLASMA);
+.int ammo_fuel = _STAT(FUEL);
+.int ammo_none;
+#else
.int ammo_shells;
.int ammo_nails;
.int ammo_rockets;
.int ammo_plasma;
.int ammo_fuel;
.int ammo_none;
+#endif
/** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
CLASS(Weapon, Object)
// no weapon specific image for this weapon
return false;
}
+ /** (CLIENT) weapon specific glow */
+ METHOD(Weapon, wr_glow, vector(Weapon this)) { return '0 0 0'; }
/** (SERVER) the weapon is dropped */
METHOD(Weapon, wr_drop, void(Weapon this)) {}
/** (SERVER) a weapon is picked up */
// other useful macros
#define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).m_name)
+#define WEP_NAME(wpn) ((Weapons_from(wpn)).m_name)
#endif
weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
else
#endif
- weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+ weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
}
if((!actor.arc_beam) || wasfreed(actor.arc_beam))
}
METHOD(Arc, wr_pickup, void(entity thiswep))
{
- if ( !client_hasweapon(self, WEP_ARC.m_id, false, false) &&
+ if ( !client_hasweapon(self, thiswep, false, false) &&
weapon_dropevent_item.arc_overheat > time )
{
self.arc_overheat = weapon_dropevent_item.arc_overheat;
METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
}
if(fire & 1)
METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else {
if(fire & 1)
{
if(!ammo_amount)
{
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
return;
}
}
self.hagar_warning = false;
// we aren't checking ammo during an attack, so we must do it here
- Weapon w = get_weaponinfo(self.weapon);
- if(!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
+ if(!(thiswep.wr_checkammo1(thiswep) + thiswep.wr_checkammo2(thiswep)))
if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
{
// note: this doesn't force the switch
if(loadable_secondary)
W_Hagar_Attack2_Load(thiswep, weaponentity); // must always run each frame
if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
{
if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hagar, refire)))
if(actor.BUTTON_ATCK)
{
- Weapon w = get_weaponinfo(actor.weapon);
- if(!w.wr_checkammo1(w))
+ if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else if(fire & 1)
{
if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
{
actor.ammo_fuel = 0;
actor.hook_state |= HOOK_REMOVING;
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
}
}
}
}
if(actor.BUTTON_ATCK)
{
- Weapon w = get_weaponinfo(actor.weapon);
- if(!w.wr_checkammo2(w))
+ if(!thiswep.wr_checkammo2(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
return;
}
- Weapon w = get_weaponinfo(actor.weapon);
- if(!w.wr_checkammo1(w))
+ if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(WEP_CVAR(machinegun, reload_ammo) && actor.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
if(WEP_CVAR(machinegun, mode) == 1)
{
if(fire & 2)
if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
{
- Weapon w = get_weaponinfo(actor.weapon);
- if(!w.wr_checkammo2(w))
+ if(!thiswep.wr_checkammo2(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
{
// not if we're holding the minelayer without enough ammo, but can detonate existing mines
if(!(W_MineLayer_PlacedMines(false) && actor.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo))) {
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
}
}
else if(fire & 1)
METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(autocvar_g_balance_mortar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else if(fire & 1)
{
if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(mortar, refire)))
}
.void() rifle_bullethail_attackfunc;
-.float rifle_bullethail_frame;
+.WFRAME rifle_bullethail_frame;
.float rifle_bullethail_animtime;
.float rifle_bullethail_refire;
void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponentity, int fire)
}
}
-void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, float fr, float animtime, float refire)
+void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, WFRAME fr, float animtime, float refire)
{SELFPARAM();
// if we get here, we have at least one bullet to fire
AttackFunc();
METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(autocvar_g_balance_rifle_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
{
actor.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), actor.rifle_accumulator, time);
if(WEP_CVAR(rifle, secondary))
{
if(WEP_CVAR_SEC(rifle, reload)) {
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
{
if(weapon_prepareattack_check(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(rifle, refire)))
METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
if(autocvar_g_balance_seeker_reload_ammo && actor.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else if(fire & 1)
{
if(WEP_CVAR(seeker, type) == 1)
if(a < ALPHA_MIN_VISIBLE) { remove(self); }
// WEAPONTODO: save this only once when creating the entity
- vector sw_color = getcsqcplayercolor(self.sv_entnum - 1); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
+ vector sw_color = entcs_GetColor(self.sv_entnum - 1); // GetTeamRGB(entcs_GetTeam(self.sv_entnum));
// WEAPONTODO: trace to find what we actually hit
vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance));
// alternate secondary weapon frames
void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- Weapon w = get_weaponinfo(actor.weapon);
- if (!w.wr_checkammo2(w))
+ if (!thiswep.wr_checkammo2(thiswep))
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
}
void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- Weapon w = get_weaponinfo(actor.weapon);
- if (!w.wr_checkammo2(w))
+ if (!thiswep.wr_checkammo2(thiswep))
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
{
// don't force reload an empty shotgun if its melee attack is active
if(WEP_CVAR(shotgun, secondary) < 2) {
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
}
}
else
WriteCoord(MSG_BROADCAST, v.y);
WriteCoord(MSG_BROADCAST, v.z);
WriteByte(MSG_BROADCAST, hit);
- WriteShort(MSG_BROADCAST, num_for_edict(player));
+ WriteByte(MSG_BROADCAST, num_for_edict(player));
WriteByte(MSG_BROADCAST, player.team);
}
#elif defined(CSQC)
string tex = "particles/lgbeam";
if(this.cnt)
tex = "particles/gauntletbeam";
- vector rgb = getcsqcplayercolor(this.sv_entnum - 1);
+ vector rgb;
+ //entity e = CSQCModel_server2csqc(this.sv_entnum - 1);
+ //if (e == NULL)
+ //{
+ rgb = colormapPaletteColor(stof(getplayerkeyvalue(this.sv_entnum - 1, "colors")) & 0x0F, true);
+ //rgb = '1 1 1';
+ //}
+ //else
+ // rgb = e.glowmod;
rgb *= (1 + autocvar_cl_vaporizerbeam_colorboost);
float fail = (self.nextthink - time);
this.vorg1_x = ReadCoord(); this.vorg1_y = ReadCoord(); this.vorg1_z = ReadCoord();
this.vorg2_x = ReadCoord(); this.vorg2_y = ReadCoord(); this.vorg2_z = ReadCoord();
this.cnt = ReadByte();
- this.sv_entnum = ReadShort();
+ int myowner = ReadByte();
+ this.owner = playerslots[myowner - 1];
+ this.sv_entnum = myowner;
this.team = ReadByte() - 1;
if(autocvar_cl_vaporizerbeam_particle)
float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
// if the laser uses load, we also consider its ammo for reloading
if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else if(WEP_CVAR(vaporizer, reload_ammo) && actor.clip_load < vaporizer_ammo) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
}
if((fire & 1) && (actor.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(actor))
{
#endif
#ifdef IMPLEMENTATION
+REGISTER_STAT(WEP_CVAR_vortex_charge, bool, WEP_CVAR(vortex, charge))
+REGISTER_STAT(WEP_CVAR_vortex_charge_animlimit, float, WEP_CVAR(vortex, charge_animlimit))
+
+#if defined(CSQC)
+float autocvar_g_weapon_charge_colormod_red_full;
+float autocvar_g_weapon_charge_colormod_red_half;
+float autocvar_g_weapon_charge_colormod_green_full;
+float autocvar_g_weapon_charge_colormod_blue_full;
+float autocvar_g_weapon_charge_colormod_blue_half;
+float autocvar_g_weapon_charge_colormod_green_half;
+float autocvar_g_weapon_charge_colormod_hdrmultiplier;
+
+METHOD(Vortex, wr_glow, vector(Vortex this))
+{
+ if (!STAT(WEP_CVAR_vortex_charge)) return '0 0 0';
+ float charge = STAT(VORTEX_CHARGE);
+ float animlimit = STAT(WEP_CVAR_vortex_charge_animlimit);
+ vector g;
+ g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
+ g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, charge / animlimit);
+ g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, charge / animlimit);
+ if (charge > animlimit)
+ {
+ g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (charge - animlimit) / (1 - animlimit);
+ g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (charge - animlimit) / (1 - animlimit);
+ g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (charge - animlimit) / (1 - animlimit);
+ }
+ return g;
+}
+#endif
+
REGISTER_NET_TEMP(TE_CSQC_VORTEXBEAMPARTICLE)
#if defined(SVQC)
particles_alphamin = particles_alphamax = particles_fade = charge;
if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos))
- if(autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
+ if(autocvar_cl_particles_oldvortexbeam && (STAT(ALLOW_OLDVORTEXBEAM) || isdemo()))
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
else
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
}
if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
+ thiswep.wr_reload(thiswep);
} else
{
if(fire & 1)
#define pointparticles __pointparticles
#define setmodel _setmodel
+#define STAT_FRAGLIMIT _STAT_FRAGLIMIT
+#define STAT_TIMELIMIT _STAT_TIMELIMIT
+#define STAT_MOVEVARS_TICRATE _STAT_MOVEVARS_TICRATE
+#define STAT_MOVEVARS_TIMESCALE _STAT_MOVEVARS_TIMESCALE
+#define STAT_MOVEVARS_GRAVITY _STAT_MOVEVARS_GRAVITY
+
#include "upstream/csprogsdefs.qc"
#undef true
#undef pointparticles
#undef setmodel
+#undef STAT_FRAGLIMIT
+#undef STAT_TIMELIMIT
+#undef STAT_MOVEVARS_TICRATE
+#undef STAT_MOVEVARS_TIMESCALE
+#undef STAT_MOVEVARS_GRAVITY
+
#pragma noref 0
#endif
--- /dev/null
+# CSQC
+
+```
+
+// input:
+// self
+.void() predraw;
+
+// input:
+// time
+// self
+.void() think;
+
+// 0 = keydown, key, character (EXT_CSQC)
+// 1 = keyup, key, character (EXT_CSQC)
+// 2 = mousemove relative, x, y (EXT_CSQC)
+// 3 = mousemove absolute, x, y (DP_CSQC)
+bool CSQC_InputEvent(int eventtype, int x, int y);
+
+void CSQC_UpdateView(int width, int height);
+bool CSQC_ConsoleCommand(string cmd);
+bool CSQC_Parse_TempEntity();
+bool CSQC_Parse_StuffCmd(string msg);
+bool CSQC_Parse_Print(string msg);
+bool CSQC_Parse_CenterPrint(string msg);
+bool CSQC_Event_Sound(int ent, int channel, string sample, float volume, float attenuation, vector pos, float speed, int flags);
+
+entity CSQC_Ent_Spawn(int entnum);
+void CSQC_Ent_Update(bool isnew);
+void CSQC_Ent_Remove();
+
+void CSQC_Init();
+void CSQC_Shutdown();
+
+// input:
+// time
+// self
+// v_forward: forward
+// v_right: right
+// v_up: up
+// output:
+// origin
+// v_forward: forward
+// v_right: right
+// v_up: up
+// trace_endpos: visorigin
+.vector camera_transform(vector pos, vector ang);
+
+```
+
+# SVQC
+
+```
+
+.entity clientcamera;
+
+// input:
+// time
+// self
+void ClientDisconnect();
+
+// input:
+// time
+void SV_Shutdown();
+
+// input:
+// time
+void SV_PausedTic(float elapsed);
+
+// input:
+// time
+// self
+void SV_ChangeTeam(int color);
+
+// input:
+// time
+// self
+void ClientKill();
+
+// input:
+// time
+// self
+void RestoreGame();
+
+// input:
+// time
+// self
+// parm1..n
+void ClientConnect();
+
+// input:
+// time
+// self
+// parm1..n
+void PutClientInServer();
+
+// return false to remove
+.bool SendEntity(entity to, int sf);
+
+// input:
+// time
+// self
+void SV_OnEntityPreSpawnFunction();
+
+// input:
+// time
+// self
+void SV_OnEntityNoSpawnFunction();
+
+// input:
+// time
+// self
+void SV_OnEntityPostSpawnFunction();
+
+// input:
+// time
+// output:
+// parm1..n
+void SetNewParms();
+
+// input:
+//
+.bool customizeentityforclient();
+
+// input:
+// time
+// self
+// output:
+// parm1..n
+void SetChangeParms();
+
+// input:
+// time
+// self
+// other
+// trace_allsolid
+// trace_startsolid
+// trace_fraction
+// trace_inwater
+// trace_inopen
+// trace_endpos: self.origin
+// trace_plane_normal
+// trace_plane_dist
+// trace_ent: other
+// trace_dpstartcontents
+// trace_dphitcontents
+// trace_dphitq3surfaceflags
+// trace_dphittexturename
+.void touch();
+
+// when .watertype changes:
+.void contentstransition(int prev, int current);
+
+// input:
+// time
+// self
+// other
+.void blocked();
+
+// input:
+// time
+// self
+.void movetypesteplandevent(vector vel);
+
+// input:
+// time
+// self
+void PlayerPreThink();
+
+// input:
+// time
+// self
+void PlayerPostThink();
+
+// input:
+// time
+// frametime
+void StartFrame();
+
+// input:
+// time
+void EndFrame();
+
+// input:
+// time
+// self
+void SV_PlayerPhysics();
+
+// input:
+// time
+// self
+void SV_ParseClientCommand(string cmd);
+
+```
+
+# MENUQC
+
+```
+
+void m_keydown(int key, int ascii);
+
+void m_keyup(int key, int ascii);
+
+void m_draw(int width, int height);
+
+void m_toggle(int mode);
+
+int m_gethostcachecategory(int entry);
+
+void m_shutdown();
+
+void m_init();
+
+```
+
+# All
+
+```
+
+void URI_Get_Callback(int id, int status, string data);
+
+void GameCommand(string cmd);
+
+```
#include "cvar.qh"
#include "defer.qh"
#include "draw.qh"
+#include "enumclass.qh"
#include "file.qh"
#include "functional.qh"
#include "i18n.qh"
#include "string.qh"
#include "struct.qh"
#include "test.qc"
+#include "unsafe.qh"
#include "urllib.qc"
#include "vector.qh"
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
-typedef int ArrayList;
+typedef entity ArrayList;
+.int al_buf;
+.int al_len;
-#define AL_declare(this) ArrayList this; int this##_len = (0)
-#define AL_init(this, n, default, T) \
+#define AL_NEW(this, n, default, T) \
do \
{ \
- this = buf_create(); \
- this##_len = n; \
- for (int i = 0; i < this##_len; ++i) \
+ ArrayList _al = this = new(ArrayList); \
+ make_pure(_al); \
+ _al.al_buf = buf_create(); \
+ for (int i = 0, _n = _al.al_len = n; i < _n; ++i) \
{ \
const _AL_type__##T() it = default; \
AL_set##T(this, i, it); \
} \
} \
while (0)
-#define AL_delete(this) buf_del(this)
+
+#define AL_DELETE(this) \
+ do \
+ { \
+ buf_del(this.al_buf); \
+ remove(this); \
+ this = NULL; \
+ } \
+ while (0)
#define _AL_type__s() string
-#define AL_gets(this, idx) bufstr_get(this, idx)
-#define AL_sets(this, idx, val) bufstr_set(this, idx, val)
+#define AL_gets(this, idx) bufstr_get(this.al_buf, idx)
+#define AL_sets(this, idx, val) bufstr_set(this.al_buf, idx, val)
#define _AL_type__f() float
#define AL_getf(this, idx) stof(AL_gets(this, idx))
do \
{ \
const noref ArrayList _al = this; \
- for (int i = 0, n = this##_len; i < n; ++i) \
+ for (int i = 0, n = _al.al_len; i < n; ++i) \
{ \
const noref _AL_type__##T() it = AL_get##T(_al, i); \
if (cond) { body } \
}
void CSQC_ClientMovement_PlayerMove_Frame(entity this);
-void _Movetype_Physics_Frame(entity this, float movedt);
+void _Movetype_Physics_ClientFrame(entity this, float movedt);
void Movetype_Physics_Spam(entity this) // optimized
{
- _Movetype_Physics_Frame(this, PHYS_INPUT_TIMELENGTH);
+ _Movetype_Physics_ClientFrame(this, PHYS_INPUT_TIMELENGTH);
if(wasfreed(this))
return;
this.avelocity = this.move_avelocity;
this.velocity = this.move_velocity;
this.angles = this.move_angles;
+ this.flags = BITSET(this.flags, FL_ONGROUND, boolean(this.move_flags & FL_ONGROUND));
+ this.flags = BITSET(this.flags, FL_WATERJUMP, boolean(this.move_flags & FL_WATERJUMP));
+ this.waterlevel = this.move_waterlevel;
+ this.watertype = this.move_watertype;
setorigin(this, this.move_origin);
}
+void CSQCPlayer_CheckWater(entity this)
+{
+ this.move_origin = this.origin;
+ this.move_waterlevel = this.waterlevel;
+ this.move_watertype = this.watertype;
+ _Movetype_CheckWater(this);
+ this.waterlevel = this.move_waterlevel;
+ this.watertype = this.move_watertype;
+}
+
void CSQCPlayer_Physics(entity this)
{
if(autocvar_cl_movement)
{
+ if(autocvar_cl_movement == 3)
+ CSQCPlayer_CheckWater(this); // we apparently need to check water *before* physics so it can use this for water jump
+
CSQC_ClientMovement_PlayerMove_Frame(this);
if(autocvar_cl_movement == 3)
{
this.move_origin = this.origin;
this.move_angles = this.angles;
- this.move_movetype = MOVETYPE_WALK; // temp
+ //this.move_movetype = MOVETYPE_WALK; // temp
this.move_velocity = this.velocity;
this.move_avelocity = this.avelocity;
+ this.move_flags = BITSET(this.move_flags, FL_ONGROUND, boolean(this.flags & FL_ONGROUND));
+ this.move_flags = BITSET(this.move_flags, FL_WATERJUMP, boolean(this.flags & FL_WATERJUMP));
+ this.move_waterlevel = this.waterlevel;
+ this.move_watertype = this.watertype;
Movetype_Physics_Spam(this);
}
+
+ this.pmove_flags =
+ ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
+ (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) |
+ ((this.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
}
}
--- /dev/null
+#ifndef ENUMCLASS_H
+#define ENUMCLASS_H
+
+#include "oo.qh"
+
+// purpose: prevent transposed parameter passing
+
+#if NDEBUG
+
+// zero overhead mode, use this for releases
+
+#define ENUMCLASS(id) typedef int id; enum {
+#define CASE(class, id) class##_##id,
+#define ENUMCLASS_END(id) };
+
+#else
+
+// edict overhead mode, use this for type checking
+
+#define ENUMCLASS(id) CLASS(id, Object)
+#define CASE(class, id) class class##_##id; STATIC_INIT(class##_##id) { class##_##id = NEW(class); }
+#define ENUMCLASS_END(id) ENDCLASS(id)
+
+#endif
+
+#endif
#define I18N_H
#include "log.qh"
+#include "unsafe.qh"
// translation helpers
string prvm_language;
return s;
}
+#ifndef CTX_CACHE
+ #define CTX_CACHE 1
+#endif
+
+#if CTX_CACHE
+ ArrayList CTX_cache;
+ STATIC_INIT(CTX_cache)
+ {
+ AL_NEW(CTX_cache, 0, string_null, s);
+ }
+ SHUTDOWN(CTX_cache)
+ {
+ AL_DELETE(CTX_cache);
+ }
+#endif
+
string CTX(string s)
{
+#if CTX_CACHE
+ int i = strid(s);
+ string c = AL_gets(CTX_cache, i);
+ if (c) return c;
+#endif
int p = strstrofs(s, "^", 0);
- if (p < 0) return s;
- return substring(s, p + 1, -1);
+ string ret = (p < 0) ? s : substring(s, p + 1, -1);
+#if CTX_CACHE
+ LOG_DEBUGF("CTX(\"%s\")\n", s);
+ AL_sets(CTX_cache, i, ret);
+#endif
+ return ret;
}
#define ZCTX(s) strzone(CTX(s))
while (0)
#if defined(CSQC)
+ entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+ entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
#elif defined(SVQC)
+ entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+ entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
#elif defined(MENUQC)
+ entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #26;
entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #27;
+ entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #88;
#endif
.entity _FOREACH_ENTITY_fld;
} \
while (0)
+#define FOREACH_ENTITY_FLAGS(fld, flags, body) \
+ do { \
+ int i = 0; \
+ for (entity it = _findchainflags_tofield(fld, flags, _FOREACH_ENTITY_next); it; (it = it._FOREACH_ENTITY_next, ++i)) \
+ { \
+ body \
+ } \
+ } \
+ while (0)
+
+#define FOREACH_ENTITY_CLASS(class, cond, body) \
+ do { \
+ int i = 0; \
+ for (entity it = _findchainstring_tofield(classname, class, _FOREACH_ENTITY_next); it; (it = it._FOREACH_ENTITY_next, ++i)) \
+ { \
+ if (cond) { body } \
+ } \
+ } \
+ while (0)
+
#define FOREACH_ENTITY(cond, body) FOREACH_ENTITY_UNORDERED(cond, body)
#define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
*/
entity LL_PUSH(LinkedList this, entity e)
{
+ assert(this);
LinkedListNode n = NEW(LinkedListNode);
n.ll_data = e;
LinkedListNode tail = n.ll_prev = this.ll_tail;
*/
entity LL_POP(LinkedList this)
{
+ assert(this);
if (!this.ll_tail) return NULL;
LinkedListNode n = this.ll_tail;
entity e = n.ll_data;
LinkedListNode prev = n.ll_prev;
- if (prev) prev.ll_next = NULL;
+ if (prev) (this.ll_tail = prev).ll_next = NULL;
else this.ll_head = this.ll_tail = NULL;
+ remove(n);
return e;
}
+#define LL_CLEAR(...) EVAL(OVERLOAD(LL_CLEAR, __VA_ARGS__))
+#define LL_CLEAR_1(this) LL_CLEAR_2(this, LAMBDA())
+#define LL_CLEAR_2(this, dtor) \
+ do \
+ { \
+ LinkedList _ll = this; \
+ assert(_ll); \
+ while (_ll.ll_tail) \
+ { \
+ entity it = LL_POP(_ll); \
+ if (!it) continue; \
+ dtor \
+ remove(it); \
+ } \
+ } \
+ while (0)
+
+#define LL_DELETE(...) EVAL(OVERLOAD(LL_DELETE, __VA_ARGS__))
+#define LL_DELETE_1(this) LL_DELETE_2(this, LAMBDA())
+#define LL_DELETE_2(this, dtor) \
+ do \
+ { \
+ LL_CLEAR(this, dtor); \
+ remove(this); \
+ this = NULL; \
+ } \
+ while (0)
+
#define LL_EACH(list, cond, body) \
do \
{ \
} \
while (0)
-#define assert(expr, ...) \
+#define assert(expr, ...) _assert(LOG_SEVERE, expr, __VA_ARGS__)
+#define ASSERT(expr, ...) _assert(LOG_FATAL, expr, __VA_ARGS__)
+#define _assert(f, expr, then) \
do \
{ \
- if (!(expr)) LOG_WARNINGF(__VA_ARGS__); \
+ if (!(expr)) \
+ { \
+ f("assertion failed: `" #expr "`\n"); \
+ then; \
+ } \
} \
while (0)
+#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
+
#define _LOG(f, level, s) f("[::"level "] ["__FILE__ ":%s:%.0f] %s", __FUNC__, __LINE__, s)
#define LOG_FATAL(...) _LOG_FATAL(strcat("", __VA_ARGS__))
} \
while (0)
-#define ASSERT(expr) \
- do \
- { \
- if (!(expr)) LOG_FATAL("assertion failed: " #expr "\n"); \
- } \
- while (0)
-
#endif
}
}
+ void Net_UnlinkEntity(entity e)
+ {
+ e.SendEntity = func_null;
+ }
+
.void() uncustomizeentityforclient;
.float uncustomizeentityforclient_set;
return v;
}
+ int _ReadSByte;
+ #define ReadSByte() (_ReadSByte = ReadByte(), (_ReadSByte & BIT(7) ? -128 : 0) + (_ReadSByte & BITS(7)))
#define ReadFloat() ReadCoord()
- vector ReadVector() { vector v; v.x = ReadFloat(); v_y = ReadFloat(); v.z = ReadFloat(); return v; }
+ vector ReadVector() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = ReadFloat(); return v; }
vector ReadVector2D() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = 0; return v; }
float ReadApproxPastTime()
(e).pure_data = true; \
} \
while (0)
+#define make_impure(e) \
+ do \
+ { \
+ (e).pure_data = false; \
+ } \
+ while (0)
#define is_pure(e) ((e).pure_data)
.string classname;
STATIC_INIT(clearentity)
{
_clearentity_ent = new(clearentity);
+ make_pure(_clearentity_ent);
}
void clearentity(entity e)
{
#ifdef CSQC
int n = e.entnum;
#endif
+ bool was_pure = is_pure(e);
copyentity(_clearentity_ent, e);
+ if (!was_pure) make_impure(e);
#ifdef CSQC
e.entnum = n;
#endif
#include "oo.qh"
#if 1
- #define _R_MAP(r, max) AL_declare(r); STATIC_INIT(r) { AL_init(r, max, NULL, e); }
+ #define _R_MAP(r, max) ArrayList r; STATIC_INIT(r) { AL_NEW(r, max, NULL, e); }
#define _R_GET(r, i) AL_gete(r, i)
#define _R_SET(r, i, e) AL_sete(r, i, e)
- #define _R_DEL(r) AL_delete(r)
+ #define _R_DEL(r) AL_DELETE(r)
#else
#define _R_MAP(r, max) entity r[max]
#define _R_GET(r, i) r[i]
if (registry##_COUNT >= registry##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(registry##_MAX)); \
entity this = id = inst; \
this.registered_id = #id; \
- this.fld = registry##_COUNT; \
- _R_SET(_##registry, registry##_COUNT, this); \
- ++registry##_COUNT; \
- if (!registry##_first) registry##_first = this; \
- if (registry##_last) registry##_last.REGISTRY_NEXT = this; \
- registry##_last = this; \
+ REGISTRY_PUSH(registry, fld, this); \
Register_##id##_init(this); \
Register_##id##_init_post(this); \
} \
ACCUMULATE_FUNCTION(Register##registry, Register_##id) \
REGISTER_INIT(id)
+#define REGISTRY_PUSH(registry, fld, it) do { \
+ it.fld = registry##_COUNT; \
+ _R_SET(_##registry, registry##_COUNT, it); \
+ ++registry##_COUNT; \
+ if (!registry##_first) registry##_first = it; \
+ if (registry##_last) registry##_last.REGISTRY_NEXT = it; \
+ registry##_last = it; \
+} while (0)
+
+#define REGISTRY_RESERVE(registry, fld, id, suffix) do { \
+ entity e = new(registry_reserved); \
+ make_pure(e); \
+ e.registered_id = #id "/" #suffix; \
+ REGISTRY_PUSH(registry, fld, e); \
+} while (0)
+
#define REGISTER_INIT(id) [[accumulate]] void Register_##id##_init(entity this)
#define REGISTER_INIT_POST(id) [[accumulate]] void Register_##id##_init_post(entity this)
#ifndef LIB_STATS_H
#define LIB_STATS_H
+// TODO: rename to 'netvars'
+
#include "registry.qh"
#include "sort.qh"
.int m_id;
+typedef vector vectori;
+#define REGISTER_STAT(...) EVAL(OVERLOAD(REGISTER_STAT, __VA_ARGS__))
#if defined(CSQC)
/** Get all stats and store them as globals, access with `STAT(ID)` */
void stats_get() {}
#define getstat_int(id) getstati(id, 0, 24)
#define getstat_bool(id) boolean(getstati(id))
#define getstat_float(id) getstatf(id)
+ #define getstat_vector(id) vec3(getstat_float(id + 0), getstat_float(id + 1), getstat_float(id + 2))
+ #define getstat_vectori(id) vec3(getstat_int(id + 0), getstat_int(id + 1), getstat_int(id + 2))
#define _STAT(id) g_stat_##id
- #define REGISTER_STAT(id, type) \
- type _STAT(id); \
- REGISTER(Stats, STAT, id, m_id, new(stat)) \
+ #define REGISTER_STAT_2(id, T) \
+ T _STAT(id); \
+ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
{ \
make_pure(this); \
+ if (#T == "vector" || #T == "vectori") { \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
} \
[[accumulate]] void stats_get() \
{ \
- _STAT(id) = getstat_##type(STAT_##id.m_id); \
+ _STAT(id) = getstat_##T(STAT_##id.m_id); \
}
+ #define REGISTER_STAT_3(x, T, expr) REGISTER_STAT(x, T)
#elif defined(SVQC)
/** Add all registered stats, access with `STAT(ID, player)` or `.type stat = _STAT(ID); player.stat` */
void stats_add() {}
#define addstat_int(id, fld) addstat(id, AS_INT, fld)
#define addstat_bool(id, fld) addstat(id, AS_INT, fld)
#define addstat_float(id, fld) addstat(id, AS_FLOAT, fld)
+ #define addstat_vector(id, fld) do { \
+ addstat_float(id + 0, fld##_x); \
+ addstat_float(id + 1, fld##_y); \
+ addstat_float(id + 2, fld##_z); \
+ } while (0)
+ #define addstat_vectori(id, fld) do { \
+ addstat_int(id + 0, fld##_x); \
+ addstat_int(id + 1, fld##_y); \
+ addstat_int(id + 2, fld##_z); \
+ } while (0)
const int AS_STRING = 1;
const int AS_INT = 2;
const int AS_FLOAT = 8;
+ .int __stat_null;
+ /** Prevent engine stats being sent */
+ STATIC_INIT(stats_clear)
+ {
+ int r = 32;
+ for (int i = 0, n = 256 - r; i < n; ++i) {
+ addstat(r + i, AS_INT, __stat_null);
+ }
+ }
+
#define _STAT(id) stat_##id
- #define REGISTER_STAT(id, type) \
- .type _STAT(id); \
- REGISTER(Stats, STAT, id, m_id, new(stat)) \
+ #define REGISTER_STAT_2(id, T) \
+ .T _STAT(id); \
+ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
{ \
make_pure(this); \
+ if (#T == "vector" || #T == "vectori") { \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
} \
[[accumulate]] void stats_add() \
{ \
- addstat_##type(STAT_##id.m_id, _STAT(id)); \
+ addstat_##T(STAT_##id.m_id, _STAT(id)); \
}
+ void GlobalStats_update(entity this) {}
+ #define REGISTER_STAT_3(x, T, expr) \
+ REGISTER_STAT(x, T); \
+ [[accumulate]] void GlobalStats_update(entity this) { STAT(x, this) = (expr); } \
+ STATIC_INIT(worldstat_##x) { entity this = world; STAT(x, this) = (expr); }
#else
- #define REGISTER_STAT(id, type)
+ #define REGISTER_STAT_2(id, type)
+ #define REGISTER_STAT_3(x, T, expr)
#endif
-const int STATS_ENGINE_RESERVE = 32 + (8 * 3); // Not sure how to handle vector stats yet, reserve them too
+const int STATS_ENGINE_RESERVE = 32;
-REGISTRY(Stats, 220 - STATS_ENGINE_RESERVE)
+REGISTRY(Stats, 256 - STATS_ENGINE_RESERVE)
REGISTER_REGISTRY(Stats)
REGISTRY_SORT(Stats)
REGISTRY_CHECK(Stats)
--- /dev/null
+#ifndef UNSAFE_H
+#define UNSAFE_H
+
+#define reinterpret_cast(T, it) _unsafe_cast_##T(0, it)
+#define X(T) T _unsafe_cast_##T(int dummy, ...) { return ...(0, T); }
+X(float)
+X(entity)
+X(string)
+typedef float(...) rawfunc;
+X(rawfunc)
+#undef X
+
+#define strid(s) etof(reinterpret_cast(entity, s))
+
+#endif
/** requires the same as boxesoverlap, but is a stronger condition */
float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) { return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z; }
+#define PITCH(v) ((v).x)
+#define YAW(v) ((v).y)
+#define ROLL(v) ((v).z)
+
+#define MAKEVECTORS(f, angles, forward, right, up) do { \
+ f(angles); \
+ forward = v_forward; \
+ right = v_right; \
+ up = v_up; \
+} while (0)
noref vector _vec2;
#define vec2(v) (_vec2 = (v), _vec2.z = 0, _vec2)
self.drawmask = MASK_NORMAL;
}
+void WarpZone_Touch ();
NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
{
warpzone_warpzones_exist = 1;
// how to draw
// engine currently wants this
self.predraw = WarpZone_Fade_PreDraw;
+
+ //self.move_touch = WarpZone_Touch;
return true;
}
void WarpZone_StoreProjectileData(entity e)
{
+#ifdef SVQC
e.warpzone_oldorigin = e.origin;
e.warpzone_oldvelocity = e.velocity;
e.warpzone_oldangles = e.angles;
+#elif defined(CSQC)
+ e.warpzone_oldorigin = e.move_origin;
+ e.warpzone_oldvelocity = e.move_velocity;
+ e.warpzone_oldangles = e.move_angles;
+#endif
}
void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
{
+#ifdef SVQC
setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch
player.oldorigin = to; // for DP's unsticking
player.angles = to_angles;
player.fixangle = true;
player.velocity = to_velocity;
+#elif defined(CSQC)
+ player.move_origin = to;
+ player.move_angles = to_angles;
+ player.move_velocity = to_velocity;
+#endif
BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
if(IS_PLAYER(player))
+#ifdef SVQC
BITCLR_ASSIGN(player.flags, FL_ONGROUND);
+#elif defined(CSQC)
+ BITCLR_ASSIGN(player.move_flags, FL_ONGROUND);
+#endif
WarpZone_PostTeleportPlayer_Callback(player);
}
+#ifdef SVQC
bool WarpZone_Teleported_Send(entity to, int sf)
{SELFPARAM();
WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
WriteCoord(MSG_ENTITY, self.angles.z);
return true;
}
+#endif
float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
{
vector o0, a0, v0, o1, a1, v1, o10;
+#ifdef SVQC
o0 = player.origin + player.view_ofs;
v0 = player.velocity;
a0 = player.angles;
+#elif defined(CSQC)
+ o0 = player.move_origin + player.view_ofs;
+ v0 = player.move_velocity;
+ a0 = player.move_angles;
+#endif
o10 = o1 = WarpZone_TransformOrigin(wz, o0);
v1 = WarpZone_TransformVelocity(wz, v0);
if (!IS_NOT_A_CLIENT(player))
- a1 = WarpZone_TransformVAngles(wz, player.v_angle);
+ a1 = WarpZone_TransformVAngles(wz, PHYS_INPUT_ANGLES(player));
else
a1 = WarpZone_TransformAngles(wz, a0);
player.warpzone_teleport_finishtime = time;
player.warpzone_teleport_zone = wz;
+#ifdef SVQC
// prevent further teleports back
float dt = (o1 - o10) * v1 * (1 / (v1 * v1));
- if(dt < sys_frametime)
- player.warpzone_teleport_finishtime += sys_frametime - dt;
+ if(dt < PHYS_INPUT_FRAMETIME)
+ player.warpzone_teleport_finishtime += PHYS_INPUT_FRAMETIME - dt;
+#endif
#ifndef WARPZONE_USE_FIXANGLE
+ #ifdef SVQC
if(IS_VEHICLE(player) && player.owner)
player = player.owner; // hax
if(IS_PLAYER(player))
ts.effects = EF_NODEPTHTEST;
ts.angles = wz.warpzone_transform;
}
+ #elif defined(CSQC)
+ setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(wz, getpropertyvec(VF_CL_VIEWANGLES)));
+ //if(checkextension("DP_CSQC_ROTATEMOVES"))
+ //CL_RotateMoves(wz.warpzone_transform);
+ #endif
#endif
return 1;
return;
// FIXME needs a better check to know what is safe to teleport and what not
+#ifdef SVQC
if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity)
+#elif defined(CSQC)
+ if(other.move_movetype == MOVETYPE_NONE || other.move_movetype == MOVETYPE_FOLLOW || other.tag_networkentity)
+#endif
return;
if(WarpZoneLib_ExactTrigger_Touch())
return;
+#ifdef SVQC
if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
+#elif defined(CSQC)
+ if(WarpZone_PlaneDist(self, other.move_origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
+#endif
return;
float f;
float d;
d = 24 + max(vlen(other.mins), vlen(other.maxs));
if(IS_NOT_A_CLIENT(other))
+ #ifdef SVQC
f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d);
+ #elif defined(CSQC)
+ f = -d / bound(frametime * d * 1, frametime * vlen(other.move_velocity), d);
+ #endif
else
f = -1;
if(WarpZone_Teleport(self, other, f, 0))
{
+#ifdef SVQC
string save1, save2;
activator = other;
if (!self.target) self.target = save1;
if (!self.target2) self.target2 = save2;
setself(this);
+#endif
}
else
{
}
}
+#ifdef SVQC
bool WarpZone_Send(entity to, int sendflags)
{SELFPARAM();
WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE);
{SELFPARAM();
vector o0, v0;
- o0 = player.origin + player.view_ofs;
- v0 = player.velocity;
+ .vector orgvec, velvec;
+#ifdef SVQC
+ orgvec = origin;
+ velvec = velocity;
+#elif defined(CSQC)
+ orgvec = move_origin;
+ velvec = move_velocity;
+#endif
+
+ o0 = player.orgvec + player.view_ofs;
+ v0 = player.velvec;
// if we teleported shortly before, abort
if(time <= player.warpzone_teleport_finishtime + 0.1)
LOG_INFO("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n");
#endif
LOG_INFO("Entity type: ", player.classname, "\n");
- LOG_INFO("Origin: ", vtos(player.origin), "\n");
- LOG_INFO("Velocity: ", vtos(player.velocity), "\n");
+ LOG_INFO("Origin: ", vtos(player.orgvec), "\n");
+ LOG_INFO("Velocity: ", vtos(player.velvec), "\n");
#ifdef WARPZONELIB_REMOVEHACK
return 0;
#else
// retry previous move
+#ifdef SVQC
setorigin(player, player.warpzone_oldorigin);
- player.velocity = player.warpzone_oldvelocity;
+#elif defined(CSQC)
+ player.move_origin = player.warpzone_oldorigin;
+#endif
+ player.velvec = player.warpzone_oldvelocity;
if(WarpZone_Teleport(wz, player, 0, 1))
{
entity oldself;
else
{
setorigin(player, o0 - player.view_ofs);
- player.velocity = v0;
+ player.velvec = v0;
}
return +1;
#endif
}
#endif
+#endif
float WarpZone_Projectile_Touch()
{SELFPARAM();
if(time == self.warpzone_teleport_time)
return true;
+#ifdef SVQC
#ifdef WARPZONELIB_KEEPDEBUG
// this SEEMS to not happen at the moment, but if it did, it would be more reliable
{
if(WarpZone_Projectile_Touch_ImpactFilter_Callback())
return true;
+#endif
return false;
}
+#ifdef SVQC
+
void WarpZone_InitStep_FindOriginTarget()
{SELFPARAM();
if(self.killtarget != "")
}
#endif
}
+
+#endif
#ifndef LIB_WARPZONE_SERVER_H
#define LIB_WARPZONE_SERVER_H
+#ifdef SVQC
void WarpZone_StartFrame();
float WarpZone_Projectile_Touch();
void WarpZone_PostInitialize_Callback();
#endif
+
+#endif
if (argv(0) == "directmenu" || argv(0) == "directpanelhudmenu")
{
string filter = string_null;
- if (argv(0) == "directpanelhudmenu") filter = strzone("HUD");
+ if (argv(0) == "directpanelhudmenu") filter = "HUD";
if (argc == 1)
{
m_play_click_sound(MENU_SOUND_OPEN);
m_goto(strcat(filter, argv(1))); // switch to a menu item
}
- if (filter) strunzone(filter);
return;
}
{
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if(argv(i) == e.netname)
s = strcat(s, " & ", e.m_name);
}
e.cvarOffValue = "0";
for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
{
- w = get_weaponinfo(i);
+ w = Weapons_from(i);
if(w.spawnflags & WEP_FLAG_HIDDEN)
continue;
if((j & 1) == 0)
int i;
- #define ADD_TO_W_LIST(pred) do { \
- for(i = WEP_FIRST; i <= WEP_LAST; ++i) \
- { \
- wep = get_weaponinfo(i); \
- if(wep.impulse == imp && (pred)) \
- w_list = strcat(w_list, WEP_NAME(i), " / "); \
- } \
- } while(0)
-
- int imp;
- entity wep;
- string w_list = "";
- for(imp = 1; imp <= 9; ++imp)
+ #define ADD_TO_W_LIST(pred) \
+ FOREACH(Weapons, it != WEP_Null, LAMBDA( \
+ if (it.impulse != imp) continue; \
+ if (!(pred)) continue; \
+ w_list = strcat(w_list, it.m_name, " / "); \
+ ))
+
+ for(int imp = 1; imp <= 9; ++imp)
{
- ADD_TO_W_LIST(!(wep.flags & WEP_FLAG_MUTATORBLOCKED) && !(wep.flags & WEP_FLAG_SUPERWEAPON));
- ADD_TO_W_LIST(wep.flags & WEP_FLAG_SUPERWEAPON);
- ADD_TO_W_LIST(wep.flags & WEP_FLAG_MUTATORBLOCKED);
+ string w_list = "";
+ ADD_TO_W_LIST(!(it.flags & WEP_FLAG_MUTATORBLOCKED) && !(it.flags & WEP_FLAG_SUPERWEAPON));
+ ADD_TO_W_LIST(it.flags & WEP_FLAG_SUPERWEAPON);
+ ADD_TO_W_LIST(it.flags & WEP_FLAG_MUTATORBLOCKED);
if(w_list)
KEYBIND_DEF(strcat("weapon_group_", itos(imp)), substring(w_list, 0, -4));
- w_list = "";
if(imp == 0)
break;
if(imp == 9)
SET_FIELD_COUNT(name, CATEGORY_FIRST, category_ent_count) \
CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \
cat = categories[name - 1] = new(slist_category); \
- cat.cat_name = strzone(#name); \
+ cat.cat_name = #name; \
cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \
cat.cat_dioverride_string = strzone(dioverride); \
cat.cat_string = strzone(str);
if(catnum) \
{ \
strunzone(categories[i].override_string); \
+ categories[i].override_string = string_null; \
categories[i].override_field = catnum; \
continue; \
} \
} \
} \
strunzone(categories[i].override_string); \
+ categories[i].override_string = string_null; \
categories[i].override_field = 0; \
}
PROCESS_OVERRIDE(cat_enoverride_string, cat_enoverride)
s = "";
for(i = 0; i < n; ++i)
{
- e = get_weaponinfo(stof(argv(i)));
+ e = Weapons_from(stof(argv(i)));
s = strcat(s, e.m_name, ", ");
}
return substring(s, 0, strlen(s) - 2);
me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
}
- e = get_weaponinfo(stof(argv(i)));
+ e = Weapons_from(stof(argv(i)));
string msg = e.m_name;
if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
msg = strcat(msg, "*");
bool autocvar_g_waypointeditor;
int autocvar_g_waypointeditor_auto;
bool autocvar_g_waypoints_for_items;
-float autocvar_g_weapon_charge_colormod_blue_full;
-float autocvar_g_weapon_charge_colormod_blue_half;
-float autocvar_g_weapon_charge_colormod_green_full;
-float autocvar_g_weapon_charge_colormod_green_half;
-float autocvar_g_weapon_charge_colormod_hdrmultiplier;
-float autocvar_g_weapon_charge_colormod_red_full;
-float autocvar_g_weapon_charge_colormod_red_half;
#define autocvar_g_weapon_stay cvar("g_weapon_stay")
bool autocvar_g_weapon_throwable;
#define autocvar_g_weaponarena cvar_string("g_weaponarena")
string autocvar_sv_defaultplayermodel_red;
string autocvar_sv_defaultplayermodel_yellow;
int autocvar_sv_defaultplayerskin;
-bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_doublejump;
bool autocvar_sv_eventlog;
bool autocvar_sv_eventlog_console;
bool autocvar_sv_eventlog_files;
if(self.weapons)
{
- Weapon w = get_weaponinfo(self.weapon);
+ Weapon w = Weapons_from(self.weapon);
w.wr_aim(w);
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
{
{
for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- entity e = get_weaponinfo(i);
+ entity e = Weapons_from(i);
if ((self.weapons & (e.m_wepset)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
self.switchweapon = i;
}
else if(self.health>WEP_CVAR(devastator, damage)*0.5)
{
if(self.velocity.z < 0)
- if(client_hasweapon(self, WEP_DEVASTATOR.m_id, true, false))
+ if(client_hasweapon(self, WEP_DEVASTATOR, true, false))
{
self.movement_x = maxspeed;
float i, other_weapon_available = false;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- Weapon w = get_weaponinfo(i);
+ Weapon w = Weapons_from(i);
// if we are out of ammo for all other weapons, it's an emergency to switch to anything else
if (w.wr_checkammo1(w) + w.wr_checkammo2(w))
other_weapon_available = true;
if(self.weapon==0)
for(i = WEP_FIRST; i <= WEP_LAST; ++i) if(i != WEP_BLASTER.m_id)
{
- if(client_hasweapon(self, i, true, false))
+ if(client_hasweapon(self, Weapons_from(i), true, false))
{
self.switchweapon = i;
return;
if ( distance > bot_distance_far ) {
for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
w = bot_weapons_far[i];
- if ( client_hasweapon(self, w, true, false) )
+ if ( client_hasweapon(self, Weapons_from(w), true, false) )
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
if ( distance > bot_distance_close) {
for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
w = bot_weapons_mid[i];
- if ( client_hasweapon(self, w, true, false) )
+ if ( client_hasweapon(self, Weapons_from(w), true, false) )
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
// Choose weapons for close distance
for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
w = bot_weapons_close[i];
- if ( client_hasweapon(self, w, true, false) )
+ if ( client_hasweapon(self, Weapons_from(w), true, false) )
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
float bot_cmd_select_weapon()
{SELFPARAM();
- float id;
-
- id = bot_cmd.bot_cmd_parm_float;
+ float id = bot_cmd.bot_cmd_parm_float;
if(id < WEP_FIRST || id > WEP_LAST)
return CMD_STATUS_ERROR;
- if(client_hasweapon(self, id, true, false))
+ if(client_hasweapon(self, Weapons_from(id), true, false))
self.switchweapon = id;
else
return CMD_STATUS_ERROR;
return 0;
// sv_clones
- if(i == CHIMPULSE_CLONE_MOVING || i == CHIMPULSE_CLONE_STANDING)
+ if(i == CHIMPULSE_CLONE_MOVING.impulse || i == CHIMPULSE_CLONE_STANDING.impulse)
if(self.lip < sv_clones)
return 1;
{
entity e, e2;
- case CHIMPULSE_SPEEDRUN_INIT: // deploy personal waypoint
+ case CHIMPULSE_SPEEDRUN_INIT.impulse: // deploy personal waypoint
// shared with regular waypoint init, so this is not a cheat by itself
if(!self.personal)
{
self.personal.invincible_finished = self.invincible_finished;
self.personal.teleport_time = time;
break; // this part itself doesn't cheat, so let's not count this
- case CHIMPULSE_CLONE_MOVING:
+ case CHIMPULSE_CLONE_MOVING.impulse:
IS_CHEAT(i, 0, 0);
makevectors (self.v_angle);
self.velocity = self.velocity + v_forward * 300;
self.velocity = self.velocity - v_forward * 300;
DID_CHEAT();
break;
- case CHIMPULSE_CLONE_STANDING:
+ case CHIMPULSE_CLONE_STANDING.impulse:
IS_CHEAT(i, 0, 0);
CopyBody(0);
self.lip += 1;
DID_CHEAT();
break;
- case CHIMPULSE_GIVE_ALL:
+ case CHIMPULSE_GIVE_ALL.impulse:
IS_CHEAT(i, 0, 0);
CheatCommand(tokenize_console("give all"));
break; // already counted as cheat
- case CHIMPULSE_SPEEDRUN:
+ case CHIMPULSE_SPEEDRUN.impulse:
IS_CHEAT(i, 0, 0);
if(self.personal)
{
else
sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
break;
- case CHIMPULSE_TELEPORT:
+ case CHIMPULSE_TELEPORT.impulse:
IS_CHEAT(i, 0, 0);
if(self.movetype == MOVETYPE_NOCLIP)
{
}
sprint(self, "Emergency teleport could not find a good location, forget it!\n");
break;
- case CHIMPULSE_R00T:
+ case CHIMPULSE_R00T.impulse:
IS_CHEAT(i, 0, 0);
RandomSelection_Init();
FOR_EACH_PLAYER(e)
#ifndef CHEATS_H
#define CHEATS_H
+#include "../common/impulses/all.qh"
+
//float autocvar_sv_cheats; // must... declare... global
float cheatcount_total;
float CheatCommand(float argc);
float CheatFrame();
-const float CHIMPULSE_SPEEDRUN_INIT = 30;
-const float CHIMPULSE_GIVE_ALL = 99;
-const float CHIMPULSE_CLONE_MOVING = 140;
-const float CHIMPULSE_SPEEDRUN = 141;
-const float CHIMPULSE_CLONE_STANDING = 142;
-const float CHIMPULSE_TELEPORT = 143;
-const float CHIMPULSE_R00T = 148;
-
const float CHRAME_DRAG = 8;
void Drag_MoveDrag(entity from, entity to); // call this from CopyBody
stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
if(autocvar_sv_gentle)
stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
+
+ MUTATOR_CALLHOOK(FixClientCvars, e);
}
float PlayerInIDList(entity p, string idlist)
======================
*/
-void SpectateCopy(entity spectatee)
-{SELFPARAM();
+void SpectateCopy(entity this, entity spectatee)
+{
MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
self.armortype = spectatee.armortype;
self.armorvalue = spectatee.armorvalue;
return false;
}
- SpectateCopy(self.enemy);
+ SpectateCopy(this, this.enemy);
return true;
}
{SELFPARAM();
if ( self.impulse )
{
- MinigameImpulse(self.impulse);
+ MinigameImpulse(self, self.impulse);
self.impulse = 0;
}
float prefered_movetype;
{SELFPARAM();
if ( self.impulse )
{
- if(MinigameImpulse(self.impulse))
+ if(MinigameImpulse(self, self.impulse))
self.impulse = 0;
}
if (self.flags & FL_JUMPRELEASED) {
if(frametime)
{
- if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
- {
- self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-
- if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
- {
- self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- }
- }
- else
- self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
-
player_powerups();
}
if (!self.crouch)
{
self.crouch = true;
- self.view_ofs = self.stat_pl_crouch_view_ofs;
- setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
+ self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self);
+ setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self));
// setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
}
}
{
if (self.crouch)
{
- tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
+ tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self);
if (!trace_startsolid)
{
self.crouch = false;
- self.view_ofs = self.stat_pl_view_ofs;
- setsize (self, self.stat_pl_min, self.stat_pl_max);
+ self.view_ofs = STAT(PL_VIEW_OFS, self);
+ setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self));
}
}
}
if(self.spectatee_status != oldspectatee_status)
{
ClientData_Touch(self);
+ if(g_race || g_cts)
+ race_InitSpectator();
}
if(self.teamkill_soundtime)
{
self.teamkill_soundtime = 0;
- setself(self.teamkill_soundsource);
- entity oldpusher = self.pusher;
- self.pusher = this;
-
- PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
-
- self.pusher = oldpusher;
- setself(this);
+ entity e = self.teamkill_soundsource;
+ entity oldpusher = e.pusher;
+ e.pusher = this;
+ PlayerSound(e, playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
+ e.pusher = oldpusher;
}
if(self.taunt_soundtime)
if(time > self.taunt_soundtime)
{
self.taunt_soundtime = 0;
- PlayerSound(playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
+ PlayerSound(self, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
}
target_voicescript_next(self);
self.clip_load = self.clip_size = 0;
}
+void DrownPlayer(entity this)
+{
+ if(this.deadflag != DEAD_NO)
+ return;
+
+ if (this.waterlevel != WATERLEVEL_SUBMERGED)
+ {
+ if(this.air_finished < time)
+ PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+ this.dmg = 2;
+ }
+ else if (this.air_finished < time)
+ { // drown!
+ if (this.pain_finished < time)
+ {
+ Damage (this, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+ this.pain_finished = time + 0.5;
+ }
+ }
+}
+
/*
=============
PlayerPostThink
//CheckPlayerJump();
if(IS_PLAYER(self)) {
+ DrownPlayer(self);
CheckRules_Player();
UpdateChatBubble();
if (self.impulse)
- ImpulseCommands();
+ ImpulseCommands(self);
if (intermission_running)
return; // intermission or finale
GetPressedKeys();
float Spectate(entity pl);
+#define SPECTATE_COPY(fld) [[accumulate]] void SpectateCopy(entity this, entity spectatee) { this.(fld) = spectatee.(fld); }
+
#endif
.entity vehicle;
+#define IMPULSE(id) _IMPULSE(IMP_##id)
+#define _IMPULSE(id) \
+ void id##_handle(entity this); \
+ STATIC_INIT_LATE(id) \
+ { \
+ id.impulse_handle = id##_handle; \
+ } \
+ void id##_handle(entity this)
+
/**
* Impulse map:
*
* 0 reserved (no input)
- * 1 to 9, 14: weapon shortcuts
- * 10: next weapon according to linear list
- * 11: most recently used weapon
- * 12: previous weapon according to linear list
- * 13: best weapon according to priority list
- * 15: next weapon according to priority list
- * 16: previous weapon according to priority list
- * 17: throw weapon
- * 18: next weapon according to sbar_hudselector 1 list
- * 19: previous weapon according to sbar_hudselector 1 list
- * 20: reload if needed
- *
- * 30 to 39: create waypoints
- * 47: clear personal waypoints
- * 48: clear team waypoints
*
* 99: loaded
*
* 230 to 253: individual weapons (up to 24)
*/
-void ImpulseCommands ()
-{SELFPARAM();
- int imp;
- vector org;
- float i;
- float m;
- entity e, e2;
+// weapon switching impulses
- imp = self.impulse;
- if (!imp || gameover)
- return;
- self.impulse = 0;
+#define X(slot) \
+ IMPULSE(weapon_group_##slot) \
+ { \
+ if (this.deadflag != DEAD_NO) return; \
+ W_NextWeaponOnImpulse(slot); \
+ }
+X(1)
+X(2)
+X(3)
+X(4)
+X(5)
+X(6)
+X(7)
+X(8)
+X(9)
+X(0)
+#undef X
- if ( self.active_minigame )
- if ( MinigameImpulse(imp) )
- return;
+// custom order weapon cycling
+
+#define X(slot, dir) \
+ IMPULSE(weapon_priority_##slot##_##dir) \
+ { \
+ if (this.vehicle) return; \
+ if (this.deadflag != DEAD_NO) return; \
+ noref int prev = -1; \
+ noref int best = 0; \
+ noref int next = +1; \
+ W_CycleWeapon(this.cvar_cl_weaponpriorities[slot], dir); \
+ }
+X(0, prev)
+X(1, prev)
+X(2, prev)
+X(3, prev)
+X(4, prev)
+X(5, prev)
+X(6, prev)
+X(7, prev)
+X(8, prev)
+X(9, prev)
+
+X(0, best)
+X(1, best)
+X(2, best)
+X(3, best)
+X(4, best)
+X(5, best)
+X(6, best)
+X(7, best)
+X(8, best)
+X(9, best)
+
+X(0, next)
+X(1, next)
+X(2, next)
+X(3, next)
+X(4, next)
+X(5, next)
+X(6, next)
+X(7, next)
+X(8, next)
+X(9, next)
+#undef X
+
+// direct weapons
+
+#define X(i) \
+ IMPULSE(weapon_byid_##i) \
+ { \
+ if (this.vehicle) return; \
+ if (this.deadflag != DEAD_NO) return; \
+ W_SwitchWeapon(Weapons_from(WEP_FIRST + i)); \
+ }
+X(0)
+X(1)
+X(2)
+X(3)
+X(4)
+X(5)
+X(6)
+X(7)
+X(8)
+X(9)
+X(10)
+X(11)
+X(12)
+X(13)
+X(14)
+X(15)
+X(16)
+X(17)
+X(18)
+X(19)
+X(20)
+X(21)
+X(22)
+X(23)
+#undef X
+
+IMPULSE(weapon_next_byid)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_NextWeapon(0);
+}
+
+IMPULSE(weapon_prev_byid)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_PreviousWeapon(0);
+}
+
+IMPULSE(weapon_next_bygroup)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_NextWeapon(1);
+}
+
+IMPULSE(weapon_prev_bygroup)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_PreviousWeapon(1);
+}
+
+IMPULSE(weapon_next_bypriority)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_NextWeapon(2);
+}
+
+IMPULSE(weapon_prev_bypriority)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_PreviousWeapon(2);
+}
+
+IMPULSE(weapon_last)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_LastWeapon();
+}
+
+IMPULSE(weapon_best)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_SwitchWeapon(Weapons_from(w_getbestweapon(this)));
+}
+
+IMPULSE(weapon_drop)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ W_ThrowWeapon(W_CalculateProjectileVelocity(this.velocity, v_forward * 750, false), '0 0 0', true);
+}
+
+IMPULSE(weapon_reload)
+{
+ if (this.vehicle) return;
+ if (this.deadflag != DEAD_NO) return;
+ if (forbidWeaponUse(this)) return;
+ Weapon w = Weapons_from(this.weapon);
+ w.wr_reload(w);
+}
+
+void ImpulseCommands(entity this)
+{
+ if (gameover) return;
+
+ int imp = this.impulse;
+ if (!imp) return;
+ this.impulse = 0;
+
+ if (MinigameImpulse(this, imp)) return;
+
+ if (timeout_status == TIMEOUT_ACTIVE) return; // don't allow any impulses while the game is paused
// allow only weapon change impulses when not in round time
- if(round_handler_IsActive() && !round_handler_IsRoundStarted())
- if(imp == 17 || (imp >= 20 && imp < 200) || imp > 253)
- return;
+ if (round_handler_IsActive() && !round_handler_IsRoundStarted())
+ {
+ #define X(id) case IMP_##id.impulse:
+ switch (imp)
+ {
+ X(weapon_group_0)
+ X(weapon_group_1)
+ X(weapon_group_2)
+ X(weapon_group_3)
+ X(weapon_group_4)
+ X(weapon_group_5)
+ X(weapon_group_6)
+ X(weapon_group_7)
+ X(weapon_group_8)
+ X(weapon_group_9)
+ X(weapon_next_byid)
+ X(weapon_prev_byid)
+ X(weapon_next_bygroup)
+ X(weapon_prev_bygroup)
+ X(weapon_next_bypriority)
+ X(weapon_prev_bypriority)
+ X(weapon_last)
+ X(weapon_best)
+ X(weapon_reload)
+ X(weapon_priority_0_prev)
+ X(weapon_priority_1_prev)
+ X(weapon_priority_2_prev)
+ X(weapon_priority_3_prev)
+ X(weapon_priority_4_prev)
+ X(weapon_priority_5_prev)
+ X(weapon_priority_6_prev)
+ X(weapon_priority_7_prev)
+ X(weapon_priority_8_prev)
+ X(weapon_priority_9_prev)
+ X(weapon_priority_0_next)
+ X(weapon_priority_1_next)
+ X(weapon_priority_2_next)
+ X(weapon_priority_3_next)
+ X(weapon_priority_4_next)
+ X(weapon_priority_5_next)
+ X(weapon_priority_6_next)
+ X(weapon_priority_7_next)
+ X(weapon_priority_8_next)
+ X(weapon_priority_9_next)
+ X(weapon_priority_0_best)
+ X(weapon_priority_1_best)
+ X(weapon_priority_2_best)
+ X(weapon_priority_3_best)
+ X(weapon_priority_4_best)
+ X(weapon_priority_5_best)
+ X(weapon_priority_6_best)
+ X(weapon_priority_7_best)
+ X(weapon_priority_8_best)
+ X(weapon_priority_9_best)
+ X(weapon_byid_0)
+ X(weapon_byid_1)
+ X(weapon_byid_2)
+ X(weapon_byid_3)
+ X(weapon_byid_4)
+ X(weapon_byid_5)
+ X(weapon_byid_6)
+ X(weapon_byid_7)
+ X(weapon_byid_8)
+ X(weapon_byid_9)
+ X(weapon_byid_10)
+ X(weapon_byid_11)
+ X(weapon_byid_12)
+ X(weapon_byid_13)
+ X(weapon_byid_14)
+ X(weapon_byid_15)
+ X(weapon_byid_16)
+ X(weapon_byid_17)
+ X(weapon_byid_18)
+ X(weapon_byid_19)
+ X(weapon_byid_20)
+ X(weapon_byid_21)
+ X(weapon_byid_22)
+ X(weapon_byid_23)
+ break;
+ default: return;
+ }
+#undef X
+ }
+
+ if (vehicle_impulse(this, imp)) return;
- if (timeout_status == TIMEOUT_ACTIVE) //don't allow any impulses while the game is paused
+ if (CheatImpulse(imp)) return;
+
+ FOREACH(IMPULSES, it.impulse == imp, {
+ void(entity) f = it.impulse_handle;
+ if (!f) continue;
+ f(this);
return;
+ });
+}
- if(self.vehicle)
- if(self.vehicle.deadflag == DEAD_NO)
+IMPULSE(use)
+{
+ PlayerUseKey();
+}
+
+IMPULSE(waypoint_personal_here)
+{
+ entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this.origin, RADARICON_WAYPOINT);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "personal waypoint spawned at location\n");
+}
+
+IMPULSE(waypoint_personal_crosshair)
+{
+ WarpZone_crosshair_trace(this);
+ entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, trace_endpos, RADARICON_WAYPOINT);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "personal waypoint spawned at crosshair\n");
+}
+
+IMPULSE(waypoint_personal_death)
+{
+ if (!this.death_origin) return;
+ entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this.death_origin, RADARICON_WAYPOINT);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "personal waypoint spawned at death location\n");
+}
+
+IMPULSE(waypoint_here_follow)
+{
+ if (!teamplay) return;
+ if (this.deadflag != DEAD_NO) return;
+ if (!MUTATOR_CALLHOOK(HelpMePing, this))
{
- if(self.vehicle.vehicles_impulse)
- if(self.vehicle.vehicles_impulse(imp))
- return;
- if(vehicle_impulse(imp))
- return;
+ entity wp = WaypointSprite_Attach(WP_Helpme, true, RADARICON_HELPME);
+ if (!wp) WaypointSprite_HelpMePing(this.waypointsprite_attachedforcarrier);
+ else WaypointSprite_Ping(wp);
}
+ sprint(this, "HELP ME attached\n");
+}
+
+IMPULSE(waypoint_here_here)
+{
+ entity wp = WaypointSprite_DeployFixed(WP_Here, false, this.origin, RADARICON_HERE);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "HERE spawned at location\n");
+}
+
+IMPULSE(waypoint_here_crosshair)
+{
+ WarpZone_crosshair_trace(this);
+ entity wp = WaypointSprite_DeployFixed(WP_Here, false, trace_endpos, RADARICON_HERE);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "HERE spawned at crosshair\n");
+}
+
+IMPULSE(waypoint_here_death)
+{
+ if (!this.death_origin) return;
+ entity wp = WaypointSprite_DeployFixed(WP_Here, false, this.death_origin, RADARICON_HERE);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "HERE spawned at death location\n");
+}
- if(CheatImpulse(imp))
+IMPULSE(waypoint_danger_here)
+{
+ entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this.origin, RADARICON_DANGER);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "DANGER spawned at location\n");
+}
+
+IMPULSE(waypoint_danger_crosshair)
+{
+ WarpZone_crosshair_trace(this);
+ entity wp = WaypointSprite_DeployFixed(WP_Danger, false, trace_endpos, RADARICON_DANGER);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "DANGER spawned at crosshair\n");
+}
+
+IMPULSE(waypoint_danger_death)
+{
+ if (!this.death_origin) return;
+ entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this.death_origin, RADARICON_DANGER);
+ if (wp) WaypointSprite_Ping(wp);
+ sprint(this, "DANGER spawned at death location\n");
+}
+
+IMPULSE(waypoint_clear_personal)
+{
+ WaypointSprite_ClearPersonal();
+ if (this.personal)
{
+ remove(this.personal);
+ this.personal = NULL;
}
- else if (imp >= 1 && imp <= 9)
+ sprint(this, "personal waypoint cleared\n");
+}
+
+IMPULSE(waypoint_clear)
+{
+ WaypointSprite_ClearOwned();
+ if (this.personal)
+ {
+ remove(this.personal);
+ this.personal = NULL;
+ }
+ sprint(this, "all waypoints cleared\n");
+}
+
+IMPULSE(navwaypoint_spawn)
+{
+ if (!autocvar_g_waypointeditor) return;
+ waypoint_schedulerelink(waypoint_spawn(this.origin, this.origin, 0));
+ bprint(strcat("Waypoint spawned at ", vtos(this.origin), "\n"));
+}
+
+IMPULSE(navwaypoint_remove)
+{
+ if (!autocvar_g_waypointeditor) return;
+ entity e = navigation_findnearestwaypoint(this, false);
+ if (!e) return;
+ if (e.wpflags & WAYPOINTFLAG_GENERATED) return;
+ bprint(strcat("Waypoint removed at ", vtos(e.origin), "\n"));
+ waypoint_remove(e);
+}
+
+IMPULSE(navwaypoint_relink)
+{
+ if (!autocvar_g_waypointeditor) return;
+ waypoint_schedulerelinkall();
+}
+
+IMPULSE(navwaypoint_save)
+{
+ if (!autocvar_g_waypointeditor) return;
+ waypoint_saveall();
+}
+
+IMPULSE(navwaypoint_unreachable)
+{
+ if (!autocvar_g_waypointeditor) return;
+ for (entity e = findchain(classname, "waypoint"); e; e = e.chain)
{
- // weapon switching impulses
- if(self.deadflag == DEAD_NO)
- W_NextWeaponOnImpulse(imp);
- //else // don't retry, as this can break weaplast bind
- // self.impulse = imp; // retry in next frame
+ e.colormod = '0.5 0.5 0.5';
+ e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
}
- else if(imp >= 10 && imp <= 20)
+ entity e2 = navigation_findnearestwaypoint(this, false);
+ navigation_markroutes(e2);
+
+ int i, m;
+
+ i = 0;
+ m = 0;
+ for (entity e = findchain(classname, "waypoint"); e; e = e.chain)
{
- if(!self.vehicle)
- if(self.deadflag == DEAD_NO)
- {
- switch(imp)
- {
- case 10:
- W_NextWeapon(0);
- break;
- case 11:
- W_LastWeapon();
- break;
- case 12:
- W_PreviousWeapon(0);
- break;
- case 13:
- W_SwitchWeapon(w_getbestweapon(self));
- break;
- case 14:
- W_NextWeaponOnImpulse(0);
- break;
- case 15:
- W_NextWeapon(2);
- break;
- case 16:
- W_PreviousWeapon(2);
- break;
- case 17:
- W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750, false), '0 0 0', true);
- break;
- case 18:
- W_NextWeapon(1);
- break;
- case 19:
- W_PreviousWeapon(1);
- break;
- case 20:
- if(!forbidWeaponUse(self)) {
- Weapon w = get_weaponinfo(self.weapon);
- w.wr_reload(w);
- }
- break;
- }
- }
- //else // don't retry, as this can break weaplast bind
- //self.impulse = imp; // retry in next frame
+ if (e.wpcost < 10000000) continue;
+ LOG_INFO("unreachable: ", etos(e), " ", vtos(e.origin), "\n");
+ e.colormod_z = 8;
+ e.effects |= EF_NODEPTHTEST | EF_BLUE;
+ ++i;
+ ++m;
}
- else if(imp == 21)
+ if (i) LOG_INFOF("%d waypoints cannot be reached from here in any way (marked with blue light)\n", i);
+ navigation_markroutes_inverted(e2);
+
+ i = 0;
+ for (entity e = findchain(classname, "waypoint"); e; e = e.chain)
{
- PlayerUseKey ();
+ if (e.wpcost < 10000000) continue;
+ LOG_INFO("cannot reach me: ", etos(e), " ", vtos(e.origin), "\n");
+ e.colormod_x = 8;
+ if (!(e.effects & EF_NODEPTHTEST)) // not already reported before
+ ++m;
+ e.effects |= EF_NODEPTHTEST | EF_RED;
+ ++i;
}
- else if(imp >= 200 && imp <= 229)
+ if (i) LOG_INFOF("%d waypoints cannot walk to here in any way (marked with red light)\n", i);
+ if (m) LOG_INFOF("%d waypoints have been marked total\n", m);
+
+ i = 0;
+ for (entity e = findchain(classname, "info_player_deathmatch"); e; e = e.chain)
{
- if(!self.vehicle)
- if(self.deadflag == DEAD_NO)
+ vector org = e.origin;
+ tracebox(e.origin, PL_MIN, PL_MAX, e.origin - '0 0 512', MOVE_NOMONSTERS, world);
+ setorigin(e, trace_endpos);
+ if (navigation_findnearestwaypoint(e, false))
{
- // custom order weapon cycling
- int i = imp % 10;
- m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
- W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
+ setorigin(e, org);
+ e.effects &= ~EF_NODEPTHTEST;
+ e.model = "";
+ }
+ else
+ {
+ setorigin(e, org);
+ LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
+ e.effects |= EF_NODEPTHTEST;
+ _setmodel(e, this.model);
+ e.frame = this.frame;
+ e.skin = this.skin;
+ e.colormod = '8 0.5 8';
+ setsize(e, '0 0 0', '0 0 0');
+ ++i;
}
- //else // don't retry, as this can break weaplast bind
- //self.impulse = imp; // retry in next frame
}
- else if(imp >= WEP_IMPULSE_BEGIN && imp <= WEP_IMPULSE_END)
+ if (i) LOG_INFOF("%d spawnpoints have no nearest waypoint (marked by player model)\n", i);
+
+ i = 0;
+ entity start = findchainflags(flags, FL_ITEM);
+ for (entity e = start; e; e = e.chain)
{
- if(!self.vehicle)
- if(self.deadflag == DEAD_NO)
- W_SwitchWeapon (imp - WEP_IMPULSE_BEGIN + WEP_FIRST);
- //else // don't retry, as this can break weaplast bind
- //self.impulse = imp; // retry in next frame
+ e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
+ e.colormod = '0.5 0.5 0.5';
}
- // deploy waypoints
- else if (imp >= 30 && imp <= 49)
+ for (entity e = start; e; e = e.chain)
{
- entity wp;
- switch(imp)
- {
- case 30:
- wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.origin, RADARICON_WAYPOINT);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "personal waypoint spawned at location\n");
- break;
- case 31:
- WarpZone_crosshair_trace(self);
- wp = WaypointSprite_DeployPersonal(WP_Waypoint, trace_endpos, RADARICON_WAYPOINT);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "personal waypoint spawned at crosshair\n");
- break;
- case 32:
- if(vlen(self.death_origin))
- {
- wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.death_origin, RADARICON_WAYPOINT);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "personal waypoint spawned at death location\n");
- }
- break;
- case 33:
- if(self.deadflag == DEAD_NO && teamplay)
- {
- if (!MUTATOR_CALLHOOK(HelpMePing, self))
- {
- wp = WaypointSprite_Attach(WP_Helpme, true, RADARICON_HELPME);
- if(!wp)
- WaypointSprite_HelpMePing(self.waypointsprite_attachedforcarrier);
- else
- WaypointSprite_Ping(wp);
- }
- sprint(self, "HELP ME attached\n");
- }
- break;
- case 34:
- wp = WaypointSprite_DeployFixed(WP_Here, false, self.origin, RADARICON_HERE);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "HERE spawned at location\n");
- break;
- case 35:
- WarpZone_crosshair_trace(self);
- wp = WaypointSprite_DeployFixed(WP_Here, false, trace_endpos, RADARICON_HERE);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "HERE spawned at crosshair\n");
- break;
- case 36:
- if(vlen(self.death_origin))
- {
- wp = WaypointSprite_DeployFixed(WP_Here, false, self.death_origin, RADARICON_HERE);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "HERE spawned at death location\n");
- }
- break;
- case 37:
- wp = WaypointSprite_DeployFixed(WP_Danger, false, self.origin, RADARICON_DANGER);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "DANGER spawned at location\n");
- break;
- case 38:
- WarpZone_crosshair_trace(self);
- wp = WaypointSprite_DeployFixed(WP_Danger, false, trace_endpos, RADARICON_DANGER);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "DANGER spawned at crosshair\n");
- break;
- case 39:
- if(vlen(self.death_origin))
- {
- wp = WaypointSprite_DeployFixed(WP_Danger, false, self.death_origin, RADARICON_DANGER);
- if(wp)
- WaypointSprite_Ping(wp);
- sprint(self, "DANGER spawned at death location\n");
- }
- break;
- case 47:
- WaypointSprite_ClearPersonal();
- if(self.personal)
- {
- remove(self.personal);
- self.personal = world;
- }
- sprint(self, "personal waypoint cleared\n");
- break;
- case 48:
- WaypointSprite_ClearOwned();
- if(self.personal)
- {
- remove(self.personal);
- self.personal = world;
- }
- sprint(self, "all waypoints cleared\n");
- break;
- }
+ if (navigation_findnearestwaypoint(e, false)) continue;
+ LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
+ e.effects |= EF_NODEPTHTEST | EF_RED;
+ e.colormod_x = 8;
+ ++i;
}
- else if(imp >= 103 && imp <= 107)
+ if (i) LOG_INFOF("%d items have no nearest waypoint and cannot be walked away from (marked with red light)\n", i);
+
+ i = 0;
+ for (entity e = start; e; e = e.chain)
{
- if(autocvar_g_waypointeditor)
- {
- switch(imp)
- {
- case 103:
- waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
- bprint(strcat("Waypoint spawned at ",vtos(self.origin),"\n"));
- break;
- case 104:
- e = navigation_findnearestwaypoint(self, false);
- if (e)
- if (!(e.wpflags & WAYPOINTFLAG_GENERATED))
- {
- bprint(strcat("Waypoint removed at ",vtos(e.origin),"\n"));
- waypoint_remove(e);
- }
- break;
- case 105:
- waypoint_schedulerelinkall();
- break;
- case 106:
- waypoint_saveall();
- break;
- case 107:
- for(e = findchain(classname, "waypoint"); e; e = e.chain)
- {
- e.colormod = '0.5 0.5 0.5';
- e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
- }
- e2 = navigation_findnearestwaypoint(self, false);
- navigation_markroutes(e2);
- i = 0;
- m = 0;
- for(e = findchain(classname, "waypoint"); e; e = e.chain)
- {
- if(e.wpcost >= 10000000)
- {
- LOG_INFO("unreachable: ", etos(e), " ", vtos(e.origin), "\n");
- e.colormod_z = 8;
- e.effects |= EF_NODEPTHTEST | EF_BLUE;
- ++i;
- ++m;
- }
- }
- if(i)
- LOG_INFO(ftos(i), " waypoints cannot be reached from here in any way (marked with blue light)\n");
- navigation_markroutes_inverted(e2);
- i = 0;
- for(e = findchain(classname, "waypoint"); e; e = e.chain)
- {
- if(e.wpcost >= 10000000)
- {
- LOG_INFO("cannot reach me: ", etos(e), " ", vtos(e.origin), "\n");
- e.colormod_x = 8;
- if(!(e.effects & EF_NODEPTHTEST)) // not already reported before
- ++m;
- e.effects |= EF_NODEPTHTEST | EF_RED;
- ++i;
- }
- }
- if(i)
- LOG_INFO(ftos(i), " waypoints cannot walk to here in any way (marked with red light)\n");
- if(m)
- LOG_INFO(ftos(m), " waypoints have been marked total\n");
- i = 0;
- for(e = findchain(classname, "info_player_deathmatch"); e; e = e.chain)
- {
- org = e.origin;
- tracebox(e.origin, PL_MIN, PL_MAX, e.origin - '0 0 512', MOVE_NOMONSTERS, world);
- setorigin(e, trace_endpos);
- if(navigation_findnearestwaypoint(e, false))
- {
- setorigin(e, org);
- e.effects &= ~EF_NODEPTHTEST;
- e.model = "";
- }
- else
- {
- setorigin(e, org);
- LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
- e.effects |= EF_NODEPTHTEST;
- _setmodel(e, self.model);
- e.frame = self.frame;
- e.skin = self.skin;
- e.colormod = '8 0.5 8';
- setsize(e, '0 0 0', '0 0 0');
- ++i;
- }
- }
- if(i)
- LOG_INFO(ftos(i), " spawnpoints have no nearest waypoint (marked by player model)\n");
- i = 0;
- entity start;
- start = findchainflags(flags, FL_ITEM);
- for(e = start; e; e = e.chain)
- {
- e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
- e.colormod = '0.5 0.5 0.5';
- }
- for(e = start; e; e = e.chain)
- {
- if(navigation_findnearestwaypoint(e, false))
- {
- }
- else
- {
- LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
- e.effects |= EF_NODEPTHTEST | EF_RED;
- e.colormod_x = 8;
- ++i;
- }
- }
- if(i)
- LOG_INFO(ftos(i), " items have no nearest waypoint and cannot be walked away from (marked with red light)\n");
- i = 0;
- for(e = start; e; e = e.chain)
- {
- org = e.origin;
- if(navigation_findnearestwaypoint(e, true))
- {
- }
- else
- {
- LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
- e.effects |= EF_NODEPTHTEST | EF_BLUE;
- e.colormod_z = 8;
- ++i;
- }
- }
- if(i)
- LOG_INFO(ftos(i), " items have no nearest waypoint and cannot be walked to (marked with blue light)\n");
- break;
- }
- }
+ if (navigation_findnearestwaypoint(e, true)) continue;
+ LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
+ e.effects |= EF_NODEPTHTEST | EF_BLUE;
+ e.colormod_z = 8;
+ ++i;
}
+ if (i) LOG_INFOF("%d items have no nearest waypoint and cannot be walked to (marked with blue light)\n", i);
}
#ifndef CL_IMPULSE_H
#define CL_IMPULSE_H
-/*
- * Impulse map:
- *
- * 0 reserved (no input)
- * 1 to 9, 14: weapon shortcuts
- * 10: next weapon according to linear list
- * 11: most recently used weapon
- * 12: previous weapon according to linear list
- * 13: best weapon according to priority list
- * 15: next weapon according to priority list
- * 16: previous weapon according to priority list
- * 17: throw weapon
- * 18: next weapon according to sbar_hudselector 1 list
- * 19: previous weapon according to sbar_hudselector 1 list
- * 20: reload if needed
- *
- * 30 to 39: create waypoints
- * 47: clear personal waypoints
- * 48: clear team waypoints
- *
- * 99: loaded
- *
- * 140: moving clone
- * 141: ctf speedrun
- * 142: fixed clone
- * 143: emergency teleport
- * 148: unfairly eliminate
- *
- * TODO:
- * 200 to 209: prev weapon shortcuts
- * 210 to 219: best weapon shortcuts
- * 220 to 229: next weapon shortcuts
- * 230 to 253: individual weapons (up to 24)
- */
-
-void ImpulseCommands ();
+void ImpulseCommands(entity this);
#endif
#include "teamplay.qh"
#include "weapons/throwing.qh"
#include "command/common.qh"
+#include "../common/anim.qh"
#include "../common/animdecide.qh"
#include "../common/csqcmodel_settings.qh"
#include "../common/deathtypes/all.qh"
animbits |= ANIMSTATE_DUCK;
animdecide_setstate(self, animbits, false);
animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND));
-
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
- {
- if (self.(weaponentity))
- {
- updateanim(self.(weaponentity));
- if (!self.(weaponentity).animstate_override)
- setanim(self.(weaponentity), self.(weaponentity).anim_idle, true, false, false);
- }
- }
}
void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
// exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
{
if(deathtype == DEATH_FALL.m_id)
- PlayerSound(playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND);
else if(self.health > 75) // TODO make a "gentle" version?
- PlayerSound(playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND);
else if(self.health > 50)
- PlayerSound(playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND);
else if(self.health > 25)
- PlayerSound(playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND);
else
- PlayerSound(playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND);
}
}
}
if(DIFF_TEAM(self, attacker))
{
if(DEATH_ISSPECIAL(deathtype))
- awep = get_weaponinfo(attacker.weapon);
+ awep = Weapons_from(attacker.weapon);
else
awep = DEATH_WEAPONOF(deathtype);
valid_damage_for_weaponstats = 1;
if(sound_allowed(MSG_BROADCAST, attacker))
{
if(deathtype == DEATH_DROWN.m_id)
- PlayerSound(playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND);
else
- PlayerSound(playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND);
+ PlayerSound(self, playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND);
}
// get rid of kill indicator
MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype);
excess = frag_damage;
- Weapon wep = get_weaponinfo(self.weapon);
+ Weapon wep = Weapons_from(self.weapon);
wep.wr_playerdeath(wep);
RemoveGrapplingHook(self);
// reset fields the weapons may use just in case
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- Weapon w = get_weaponinfo(j);
+ Weapon w = Weapons_from(j);
w.wr_resetplayer(w);
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
#ifndef SERVER_COMMANDS_ALL_H
#define SERVER_COMMANDS_ALL_H
-#include "../../common/command/commands.qh"
+#include "../../common/command/command.qh"
+REGISTRY(SERVER_COMMANDS, BITS(7))
+#define SERVER_COMMANDS_from(i) _SERVER_COMMANDS_from(i, NULL)
+REGISTER_REGISTRY(SERVER_COMMANDS)
+REGISTRY_SORT(SERVER_COMMANDS)
+
+#define SERVER_COMMAND(id, description) \
+ CLASS(servercommand_##id, Command) \
+ ATTRIB(servercommand_##id, m_name, string, #id); \
+ ATTRIB(servercommand_##id, m_description, string, description); \
+ ENDCLASS(servercommand_##id) \
+ REGISTER(SERVER_COMMANDS, CMD_SV, id, m_id, NEW(servercommand_##id)); \
+ METHOD(servercommand_##id, m_invokecmd, void(int request, entity caller, int arguments, string command))
+
+STATIC_INIT(SERVER_COMMANDS_aliases) {
+ FOREACH(SERVER_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_svcmd"))));
+}
#include "sv_cmd.qh"
sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
return;
}
- if (argc >= 3) VoiceMessage(e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
- else VoiceMessage(e, "");
+ if (argc >= 3) VoiceMessage(this, e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+ else VoiceMessage(this, e, "");
return;
}
#ifndef COMMAND_COMMON_H
#define COMMAND_COMMON_H
+#include "../../common/command/command.qh"
+REGISTRY(COMMON_COMMANDS, BITS(7))
+#define COMMON_COMMANDS_from(i) _COMMON_COMMANDS_from(i, NULL)
+REGISTER_REGISTRY(COMMON_COMMANDS)
+REGISTRY_SORT(COMMON_COMMANDS)
+
+#define COMMON_COMMAND(id, description) \
+ CLASS(commoncommand_##id, Command) \
+ ATTRIB(commoncommand_##id, m_name, string, #id); \
+ ATTRIB(commoncommand_##id, m_description, string, description); \
+ ENDCLASS(commoncommand_##id) \
+ REGISTER(COMMON_COMMANDS, CMD_SV, id, m_id, NEW(commoncommand_##id)); \
+ METHOD(commoncommand_##id, m_invokecmd, void(int request, entity caller, int arguments, string command))
+
+STATIC_INIT(COMMON_COMMANDS_aliases) {
+ FOREACH(COMMON_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_svcmd"))));
+}
+
#include "vote.qh"
#include "../../common/monsters/spawn.qh"
// ==================================
// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define COMMON_COMMANDS(request, caller, arguments, command) \
- COMMON_COMMAND("cvar_changes", CommonCommand_cvar_changes(request, caller), "Prints a list of all changed server cvars") \
- COMMON_COMMAND("cvar_purechanges", CommonCommand_cvar_purechanges(request, caller), "Prints a list of all changed gameplay cvars") \
- COMMON_COMMAND("editmob", CommonCommand_editmob(request, caller, arguments), "Modifies a monster or all monsters") \
- COMMON_COMMAND("info", CommonCommand_info(request, caller, arguments), "Request for unique server information set up by admin") \
- COMMON_COMMAND("ladder", CommonCommand_ladder(request, caller), "Get information about top players if supported") \
- COMMON_COMMAND("lsmaps", CommonCommand_lsmaps(request, caller), "List maps which can be used with the current game mode") \
- COMMON_COMMAND("printmaplist", CommonCommand_printmaplist(request, caller), "Display full server maplist reply") \
- COMMON_COMMAND("rankings", CommonCommand_rankings(request, caller), "Print information about rankings") \
- COMMON_COMMAND("records", CommonCommand_records(request, caller), "List top 10 records for the current map") \
- COMMON_COMMAND("teamstatus", CommonCommand_teamstatus(request, caller), "Show information about player and team scores") \
- COMMON_COMMAND("time", CommonCommand_time(request, caller), "Print different formats/readouts of time") \
- COMMON_COMMAND("timein", CommonCommand_timein(request, caller), "Resume the game from being paused with a timeout") \
- COMMON_COMMAND("timeout", CommonCommand_timeout(request, caller), "Call a timeout which pauses the game for certain amount of time unless unpaused") \
- COMMON_COMMAND("vote", VoteCommand(request, caller, arguments, command), "Request an action to be voted upon by players") \
- COMMON_COMMAND("who", CommonCommand_who(request, caller, arguments), "Display detailed client information about all players") \
- /* nothing */
+COMMON_COMMAND(cvar_changes, "Prints a list of all changed server cvars") { CommonCommand_cvar_changes(request, caller); }
+COMMON_COMMAND(cvar_purechanges, "Prints a list of all changed gameplay cvars") { CommonCommand_cvar_purechanges(request, caller); }
+COMMON_COMMAND(editmob, "Modifies a monster or all monsters") { CommonCommand_editmob(request, caller, arguments); }
+COMMON_COMMAND(info, "Request for unique server information set up by admin") { CommonCommand_info(request, caller, arguments); }
+COMMON_COMMAND(ladder, "Get information about top players if supported") { CommonCommand_ladder(request, caller); }
+COMMON_COMMAND(lsmaps, "List maps which can be used with the current game mode") { CommonCommand_lsmaps(request, caller); }
+COMMON_COMMAND(printmaplist, "Display full server maplist reply") { CommonCommand_printmaplist(request, caller); }
+COMMON_COMMAND(rankings, "Print information about rankings") { CommonCommand_rankings(request, caller); }
+COMMON_COMMAND(records, "List top 10 records for the current map") { CommonCommand_records(request, caller); }
+COMMON_COMMAND(teamstatus, "Show information about player and team scores") { CommonCommand_teamstatus(request, caller); }
+COMMON_COMMAND(time, "Print different formats/readouts of time") { CommonCommand_time(request, caller); }
+COMMON_COMMAND(timein, "Resume the game from being paused with a timeout") { CommonCommand_timein(request, caller); }
+COMMON_COMMAND(timeout, "Call a timeout which pauses the game for certain amount of time unless unpaused") { CommonCommand_timeout(request, caller); }
+COMMON_COMMAND(vote, "Request an action to be voted upon by players") { VoteCommand(request, caller, arguments, command); }
+COMMON_COMMAND(who, "Display detailed client information about all players") { CommonCommand_who(request, caller, arguments);}
void CommonCommand_macro_help(entity caller)
{
- #define COMMON_COMMAND(name, function, description) \
- { print_to(caller, strcat(" ^2", name, "^7: ", description)); }
-
- COMMON_COMMANDS(0, caller, 0, "");
-#undef COMMON_COMMAND
+ FOREACH(COMMON_COMMANDS, true, LAMBDA(print_to(caller, sprintf(" ^2%s^7: %s\n", it.m_name, it.m_description))));
}
float CommonCommand_macro_command(float argc, entity caller, string command)
{
- #define COMMON_COMMAND(name, function, description) \
- { if (name == strtolower(argv(0))) { function; return true; } }
-
- COMMON_COMMANDS(CMD_REQUEST_COMMAND, caller, argc, command);
-#undef COMMON_COMMAND
-
+ string c = strtolower(argv(0));
+ FOREACH(COMMON_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_COMMAND, caller, argc, command);
+ return true;
+ ));
return false;
}
float CommonCommand_macro_usage(float argc, entity caller)
{
- #define COMMON_COMMAND(name, function, description) \
- { if (name == strtolower(argv(1))) { function; return true; } }
-
- COMMON_COMMANDS(CMD_REQUEST_USAGE, caller, argc, "");
-#undef COMMON_COMMAND
-
+ string c = strtolower(argv(1));
+ FOREACH(COMMON_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_USAGE, caller, argc, "");
+ return true;
+ ));
return false;
}
void CommonCommand_macro_write_aliases(float fh)
{
- #define COMMON_COMMAND(name, function, description) \
- { CMD_Write_Alias("qc_cmd_svcmd", name, description); }
-
- COMMON_COMMANDS(0, world, 0, "");
-#undef COMMON_COMMAND
+ FOREACH(COMMON_COMMANDS, true, LAMBDA(CMD_Write_Alias("qc_cmd_svcmd", it.m_name, it.m_description)));
}
-#include "../../common/command/command.qh"
-#include "sv_cmd.qh"
+#include "all.qh"
#include "banning.qh"
#include "cmd.qh"
// ==================================
// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define SERVER_COMMANDS(request, arguments, command) \
- SERVER_COMMAND("adminmsg", GameCommand_adminmsg(request, arguments), "Send an admin message to a client directly") \
- SERVER_COMMAND("allready", GameCommand_allready(request), "Restart the server and reset the players") \
- SERVER_COMMAND("allspec", GameCommand_allspec(request, arguments), "Force all players to spectate") \
- SERVER_COMMAND("anticheat", GameCommand_anticheat(request, arguments), "Create an anticheat report for a client") \
- SERVER_COMMAND("animbench", GameCommand_animbench(request, arguments), "Benchmark model animation (LAGS)") \
- SERVER_COMMAND("bbox", GameCommand_bbox(request), "Print detailed information about world size") \
- SERVER_COMMAND("bot_cmd", GameCommand_bot_cmd(request, arguments, command), "Control and send commands to bots") \
- SERVER_COMMAND("cointoss", GameCommand_cointoss(request, arguments), "Flip a virtual coin and give random result") \
- SERVER_COMMAND("database", GameCommand_database(request, arguments), "Extra controls of the serverprogs database") \
- SERVER_COMMAND("defer_clear", GameCommand_defer_clear(request, arguments), "Clear all queued defer commands for a specific client") \
- SERVER_COMMAND("defer_clear_all", GameCommand_defer_clear_all(request), "Clear all queued defer commands for all clients") \
- SERVER_COMMAND("delrec", GameCommand_delrec(request, arguments), "Delete race time record for a map") \
- SERVER_COMMAND("effectindexdump", GameCommand_effectindexdump(request), "Dump list of effects from code and effectinfo.txt") \
- SERVER_COMMAND("extendmatchtime", GameCommand_extendmatchtime(request), "Increase the timelimit value incrementally") \
- SERVER_COMMAND("find", GameCommand_find(request, arguments), "Search through entities for matching classname") \
- SERVER_COMMAND("gametype", GameCommand_gametype(request, arguments), "Simple command to change the active gametype") \
- SERVER_COMMAND("gettaginfo", GameCommand_gettaginfo(request, arguments), "Get specific information about a weapon model") \
- SERVER_COMMAND("gotomap", GameCommand_gotomap(request, arguments), "Simple command to switch to another map") \
- SERVER_COMMAND("lockteams", GameCommand_lockteams(request), "Disable the ability for players to switch or enter teams") \
- SERVER_COMMAND("make_mapinfo", GameCommand_make_mapinfo(request), "Automatically rebuild mapinfo files") \
- SERVER_COMMAND("moveplayer", GameCommand_moveplayer(request, arguments), "Change the team/status of a player") \
- SERVER_COMMAND("nospectators", GameCommand_nospectators(request), "Automatically remove spectators from a match") \
- SERVER_COMMAND("playerdemo", GameCommand_playerdemo(request, arguments), "Control the ability to save demos of players") \
- SERVER_COMMAND("printstats", GameCommand_printstats(request), "Dump eventlog player stats and other score information") \
- SERVER_COMMAND("radarmap", GameCommand_radarmap(request, arguments), "Generate a radar image of the map") \
- SERVER_COMMAND("reducematchtime", GameCommand_reducematchtime(request), "Decrease the timelimit value incrementally") \
- SERVER_COMMAND("setbots", GameCommand_setbots(request, arguments), "Adjust how many bots are in the match") \
- SERVER_COMMAND("shuffleteams", GameCommand_shuffleteams(request), "Randomly move players to different teams") \
- SERVER_COMMAND("stuffto", GameCommand_stuffto(request, arguments), "Send a command to be executed on a client") \
- SERVER_COMMAND("trace", GameCommand_trace(request, arguments), "Various debugging tools with tracing") \
- SERVER_COMMAND("unlockteams", GameCommand_unlockteams(request), "Enable the ability for players to switch or enter teams") \
- SERVER_COMMAND("warp", GameCommand_warp(request, arguments), "Choose different level in campaign") \
- /* nothing */
+SERVER_COMMAND(adminmsg, "Send an admin message to a client directly") { GameCommand_adminmsg(request, arguments); }
+SERVER_COMMAND(allready, "Restart the server and reset the players") { GameCommand_allready(request); }
+SERVER_COMMAND(allspec, "Force all players to spectate") { GameCommand_allspec(request, arguments); }
+SERVER_COMMAND(anticheat, "Create an anticheat report for a client") { GameCommand_anticheat(request, arguments); }
+SERVER_COMMAND(animbench, "Benchmark model animation (LAGS)") { GameCommand_animbench(request, arguments); }
+SERVER_COMMAND(bbox, "Print detailed information about world size") { GameCommand_bbox(request); }
+SERVER_COMMAND(bot_cmd, "Control and send commands to bots") { GameCommand_bot_cmd(request, arguments, command); }
+SERVER_COMMAND(cointoss, "Flip a virtual coin and give random result") { GameCommand_cointoss(request, arguments); }
+SERVER_COMMAND(database, "Extra controls of the serverprogs database") { GameCommand_database(request, arguments); }
+SERVER_COMMAND(defer_clear, "Clear all queued defer commands for a specific client") { GameCommand_defer_clear(request, arguments); }
+SERVER_COMMAND(defer_clear_all, "Clear all queued defer commands for all clients") { GameCommand_defer_clear_all(request); }
+SERVER_COMMAND(delrec, "Delete race time record for a map") { GameCommand_delrec(request, arguments); }
+SERVER_COMMAND(effectindexdump, "Dump list of effects from code and effectinfo.txt") { GameCommand_effectindexdump(request); }
+SERVER_COMMAND(extendmatchtime, "Increase the timelimit value incrementally") { GameCommand_extendmatchtime(request); }
+SERVER_COMMAND(find, "Search through entities for matching classname") { GameCommand_find(request, arguments); }
+SERVER_COMMAND(gametype, "Simple command to change the active gametype") { GameCommand_gametype(request, arguments); }
+SERVER_COMMAND(gettaginfo, "Get specific information about a weapon model") { GameCommand_gettaginfo(request, arguments); }
+SERVER_COMMAND(gotomap, "Simple command to switch to another map") { GameCommand_gotomap(request, arguments); }
+SERVER_COMMAND(lockteams, "Disable the ability for players to switch or enter teams") { GameCommand_lockteams(request); }
+SERVER_COMMAND(make_mapinfo, "Automatically rebuild mapinfo files") { GameCommand_make_mapinfo(request); }
+SERVER_COMMAND(moveplayer, "Change the team/status of a player") { GameCommand_moveplayer(request, arguments); }
+SERVER_COMMAND(nospectators, "Automatically remove spectators from a match") { GameCommand_nospectators(request); }
+SERVER_COMMAND(playerdemo, "Control the ability to save demos of players") { GameCommand_playerdemo(request, arguments); }
+SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
+SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
+SERVER_COMMAND(reducematchtime, "Decrease the timelimit value incrementally") { GameCommand_reducematchtime(request); }
+SERVER_COMMAND(setbots, "Adjust how many bots are in the match") { GameCommand_setbots(request, arguments); }
+SERVER_COMMAND(shuffleteams, "Randomly move players to different teams") { GameCommand_shuffleteams(request); }
+SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameCommand_stuffto(request, arguments); }
+SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
+SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
+SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
void GameCommand_macro_help()
{
- #define SERVER_COMMAND(name, function, description) \
- { LOG_INFO(" ^2", name, "^7: ", description, "\n"); }
-
- SERVER_COMMANDS(0, 0, "");
-#undef SERVER_COMMAND
+ FOREACH(SERVER_COMMANDS, true, LAMBDA(LOG_INFOF(" ^2%s^7: %s\n", it.m_name, it.m_description)));
}
float GameCommand_macro_command(float argc, string command)
{
- #define SERVER_COMMAND(name, function, description) \
- { if (name == strtolower(argv(0))) { function; return true; } }
-
- SERVER_COMMANDS(CMD_REQUEST_COMMAND, argc, command);
-#undef SERVER_COMMAND
-
+ string c = strtolower(argv(0));
+ FOREACH(SERVER_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_COMMAND, NULL, argc, command);
+ return true;
+ ));
return false;
}
float GameCommand_macro_usage(float argc)
{
- #define SERVER_COMMAND(name, function, description) \
- { if (name == strtolower(argv(1))) { function; return true; } }
-
- SERVER_COMMANDS(CMD_REQUEST_USAGE, argc, "");
-#undef SERVER_COMMAND
-
+ string c = strtolower(argv(1));
+ FOREACH(SERVER_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_USAGE, NULL, argc, "");
+ return true;
+ ));
return false;
}
void GameCommand_macro_write_aliases(float fh)
{
- #define SERVER_COMMAND(name, function, description) \
- { CMD_Write_Alias("qc_cmd_sv", name, description); }
-
- SERVER_COMMANDS(0, 0, "");
-#undef SERVER_COMMAND
+ FOREACH(SERVER_COMMANDS, true, LAMBDA(CMD_Write_Alias("qc_cmd_sv", it.m_name, it.m_description)));
}
.float strength_finished = _STAT(STRENGTH_FINISHED);
.float invincible_finished = _STAT(INVINCIBLE_FINISHED);
-.float superweapons_finished;
+.float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
.float cnt; // used in too many places
.float count;
.float fade_time;
.float fade_rate;
-// weapon animation vectors:
-.vector anim_fire1;
-.vector anim_fire2;
-.vector anim_idle;
-.vector anim_reload;
-
void() player_setupanimsformodel;
-void setanim(entity e, vector anim, float looping, float override, float restart);
.string mdl;
.entity item_pickupsound_ent;
.entity item_model_ent;
-// definitions for weaponsystem
-// more WEAPONTODO: move these to their proper files
-.entity exteriorweaponentity;
-.vector weaponentity_glowmod;
-
-//.int weapon; // current weapon
-.int switchweapon = _STAT(SWITCHWEAPON);
-.int switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
-.string weaponname; // name of .weapon
-
// WEAPONTODO
.float autoswitch;
-float client_hasweapon(entity cl, float wpn, float andammo, float complain);
+bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain);
void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
// VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
.void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
-// weapon states (self.weaponentity.state)
-const int WS_CLEAR = 0; // no weapon selected
-const int WS_RAISE = 1; // raise frame
-const int WS_DROP = 2; // deselecting frame
-const int WS_INUSE = 3; // fire state
-const int WS_READY = 4; // idle frame
-
// there is 2 weapon tics that can run in one server frame
const int W_TICSPERFRAME = 2;
float playerid_last;
.float noalign; // if set to 1, the item or spawnpoint won't be dropped to the floor
-.vector spawnorigin;
-
.vector death_origin;
.vector killer_origin;
.float cvar_cl_clippedspectating;
.float cvar_cl_autoscreenshot;
.float cvar_cl_jetpack_jump;
-.float cvar_cl_movement_track_canjump;
+.float cvar_cl_movement_track_canjump = _STAT(MOVEVARS_CL_TRACK_CANJUMP);
.float cvar_cl_newusekeysupported;
.string cvar_g_xonoticversion;
// WEAPONTODO: remove this
WepSet weaponsInMap;
-.WepSet weaponsinmap;
+#define weapons _STAT(WEAPONS)
+#define weaponsinmap _STAT(WEAPONSINMAP)
.float respawn_countdown; // next number to count
string clientstuff;
.float phase;
-.int pressedkeys;
+.int pressedkeys = _STAT(PRESSED_KEYS);
.string fog;
float game_starttime; //point in time when the countdown to game start is over
float round_starttime; //point in time when the countdown to round start is over
.float stat_game_starttime = _STAT(GAMESTARTTIME);
-.float stat_round_starttime;
+.float stat_round_starttime = _STAT(ROUNDSTARTTIME);
void W_Porto_Remove (entity p);
.string message2;
-.float stat_allow_oldvortexbeam;
+.bool stat_allow_oldvortexbeam = _STAT(ALLOW_OLDVORTEXBEAM);
// reset to 0 on weapon switch
// may be useful to all weapons
.float floodcontrol_voice;
.float floodcontrol_voiceteam;
-.float stat_shotorg; // networked stat for trueaim HUD
+.float stat_shotorg = _STAT(SHOTORG); // networked stat for trueaim HUD
string matchid;
-.float last_pickup;
+.float last_pickup = _STAT(LAST_PICKUP);
-.float hit_time;
-.float typehit_time;
+.float hit_time = _STAT(HIT_TIME);
+.float typehit_time = _STAT(TYPEHIT_TIME);
-.float damage_dealt_total;
+.float damage_dealt_total = _STAT(DAMAGE_DEALT_TOTAL);
-.float stat_leadlimit;
+.float stat_leadlimit = _STAT(LEADLIMIT);
bool radar_showennemies;
.float weapon_load[Weapons_MAX];
.int ammo_none; // used by the reloading system, must always be 0
-.float clip_load;
+.float clip_load = _STAT(WEAPON_CLIPLOAD);
.float old_clip_load;
-.float clip_size;
+.float clip_size = _STAT(WEAPON_CLIPSIZE);
-.float minelayer_mines;
-.float vortex_charge;
+.float minelayer_mines = _STAT(LAYED_MINES);
+.float vortex_charge = _STAT(VORTEX_CHARGE);
.float vortex_charge_rottime;
-.float vortex_chargepool_ammo;
-.float hagar_load;
+.float vortex_chargepool_ammo = _STAT(VORTEX_CHARGEPOOL);
+.float hagar_load = _STAT(HAGAR_LOAD);
.int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
.float player_blocked;
.float weapon_blocked; // weapon use disabled
-.float frozen; // for freeze attacks
-.float revive_progress;
+.float frozen = _STAT(FROZEN); // for freeze attacks
+.float revive_progress = _STAT(REVIVE_PROGRESS);
.float revival_time; // time at which player was last revived
.float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
.entity iceblock;
.entity muzzle_flash;
.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
-.float stat_respawn_time; // shows respawn time, and is negative when awaiting respawn
+.float stat_respawn_time = _STAT(RESPAWN_TIME); // shows respawn time, and is negative when awaiting respawn
void PlayerUseKey();
{
// after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
Weapon culprit = DEATH_WEAPONOF(deathtype);
- if(!culprit) culprit = get_weaponinfo(attacker.weapon);
- else if(!(attacker.weapons & (culprit.m_wepset))) culprit = get_weaponinfo(attacker.weapon);
+ if(!culprit) culprit = Weapons_from(attacker.weapon);
+ else if(!(attacker.weapons & (culprit.m_wepset))) culprit = Weapons_from(attacker.weapon);
if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
{
}
// after a frag, choose another random weapon set
- if (!(attacker.weapons & WepSet_FromWeapon(attacker.weapon)))
- W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
+ if (!(attacker.weapons & WepSet_FromWeapon(Weapons_from(attacker.weapon))))
+ W_SwitchWeapon_Force(attacker, Weapons_from(w_getbestweapon(attacker)));
}
// FIXME fix the mess this is (we have REAL points now!)
return false;
}
-.int buffs; // TODO: remove
+.int buffs = _STAT(BUFFS); // TODO: remove
void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
{
void UpdateFrags(entity player, float f);
// NOTE: f=0 means still count as a (positive) kill, but count no frags for it
-void W_SwitchWeapon_Force(entity e, float w);
+void W_SwitchWeapon_Force(entity e, Weapon w);
entity GiveFrags_randomweapons;
void GiveFrags (entity attacker, entity targ, float f, int deathtype);
// if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
}
-void setanim(entity e, vector anim, float looping, float override, float restart)
-{
- if (!anim)
- return; // no animation was given to us! We can't use this.
-
- if (anim.x == e.animstate_startframe)
- if (anim.y == e.animstate_numframes)
- if (anim.z == e.animstate_framerate)
- {
- if(restart)
- {
- if(restart > 0)
- if(anim.y == 1) // ZYM animation
- BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
- }
- else
- return;
- }
- e.animstate_startframe = anim.x;
- e.animstate_numframes = anim.y;
- e.animstate_framerate = anim.z;
- e.animstate_starttime = servertime - 0.1 * serverframetime; // shift it a little bit into the past to prevent float inaccuracy hiccups
- e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
- e.animstate_looping = looping;
- e.animstate_override = override;
- e.frame = e.animstate_startframe;
- e.frame1time = servertime;
-}
-
-void updateanim(entity e)
-{
- if (time >= e.animstate_endtime)
- {
- if (e.animstate_looping)
- {
- e.animstate_starttime = e.animstate_endtime;
- e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
- }
- e.animstate_override = false;
- }
- e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
- //print(ftos(time), " -> ", ftos(e.frame), "\n");
-}
-
/*
==================
main
spawnfunc(info_null);
-void setanim(entity e, vector anim, float looping, float override, float restart);
-
-void updateanim(entity e);
-
-
-
/*
==================
SUB_Friction
void ClientInit_Spawn();
void WeaponStats_Init();
void WeaponStats_Shutdown();
-void Physics_AddStats();
spawnfunc(worldspawn)
{
float fd, l, j, n;
WeaponStats_Init();
- WepSet_AddStat();
- WepSet_AddStat_InMap();
- addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon);
- addstat(STAT_ROUNDSTARTTIME, AS_FLOAT, stat_round_starttime);
- addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
Nagger_Init();
- addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
- addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
- addstat(STAT_FUEL, AS_INT, ammo_fuel);
- addstat(STAT_PLASMA, AS_INT, ammo_plasma);
- addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
- addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
- addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
- addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
- addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
- addstat(STAT_HIT_TIME, AS_FLOAT, hit_time);
- addstat(STAT_DAMAGE_DEALT_TOTAL, AS_INT, damage_dealt_total);
- addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
- addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
-
- addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
- addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
-
- addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
-
- // freeze attacks
- addstat(STAT_FROZEN, AS_INT, frozen);
- addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
-
- // physics
- Physics_AddStats();
-
- // new properties
- addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
- addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
- addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
- addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
- addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
- addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
- addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
- addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
- addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
- addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
- addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
- addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
- addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
- addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
- addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
- // secrets
- addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
- addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
-
- // monsters
- addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
- addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
-
- // misc
- addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
-
next_pingtime = time + 5;
detect_maptype();
if(e.(weaponentity))
{
e.(weaponentity).effects = EF_NODRAW;
- if (e.(weaponentity).(weaponentity))
- e.(weaponentity).(weaponentity).effects = EF_NODRAW;
+ if (e.(weaponentity).weaponchild)
+ e.(weaponentity).weaponchild.effects = EF_NODRAW;
}
}
if(IS_REAL_CLIENT(e))
{
stuffcmd(e, "\nscr_printspeed 1000000\n");
- string list = autocvar_sv_intermission_cdtrack;
- for(string it; (it = car(list)); list = cdr(list))
- RandomSelection_Add(world, 0, it, 1, 1);
- if(RandomSelection_chosen_string && RandomSelection_chosen_string != "")
- stuffcmd(e, strcat("\ncd loop ", RandomSelection_chosen_string, "\n"));
+ RandomSelection_Init();
+ FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, LAMBDA(
+ RandomSelection_Add(NULL, 0, it, 1, 1);
+ ));
+ if (RandomSelection_chosen_string != "")
+ {
+ stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
+ }
msg_entity = e;
WriteByte(MSG_ONE, SVC_INTERMISSION);
}
g_weaponarena_list = "All Weapons";
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
g_weaponarena_weapons |= (e.m_wepset);
}
g_weaponarena_list = "Most Weapons";
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
if (e.spawnflags & WEP_FLAG_NORMAL)
g_weaponarena_weapons |= (e.m_wepset);
s = argv(i);
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if (e.netname == s)
{
g_weaponarena_weapons |= (e.m_wepset);
{
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- e = get_weaponinfo(i);
+ e = Weapons_from(i);
int w = want_weapon(e, false);
WepSet s = e.m_wepset;
if(w & 1)
warmup_start_weapons_defaultmask = '0 0 0';
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- e = get_weaponinfo(i);
+ e = Weapons_from(i);
int w = want_weapon(e, g_warmup_allguns);
WepSet s = (e.m_wepset);
if(w & 1)
precache_weapons |= warmup_start_weapons;
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- e = get_weaponinfo(i);
+ e = Weapons_from(i);
if(precache_weapons & (e.m_wepset)) {
e.wr_init(e);
}
game_starttime = time + cvar("g_start_delay");
for(int i = WEP_FIRST; i <= WEP_LAST; ++i) {
- Weapon w = get_weaponinfo(i);
+ Weapon w = Weapons_from(i);
w.wr_init(w);
}
string weapon_sound_output;
MUTATOR_HOOKABLE(WeaponSound, EV_WeaponSound);
-/** called when a weapon model is about to be set, allows custom paths etc. */
-#define EV_WeaponModel(i, o) \
- /**/ i(string, weapon_model) \
- /**/ i(string, weapon_model_output) \
- /**/ o(string, weapon_model_output) \
- /**/
-string weapon_model;
-string weapon_model_output;
-MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
-
/** called when an item model is about to be set, allows custom paths etc. */
#define EV_ItemModel(i, o) \
/**/ i(string, item_model) \
string monster_model;
string monster_model_output;
MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel);
+
+/**/
+#define EV_Player_ChangeTeam(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, pct_curteam) \
+ /**/ i(float, pct_newteam) \
+ /**/
+float pct_curteam;
+float pct_newteam;
+MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
#endif
.float lastground;
float total_players;
float redalive, bluealive, yellowalive, pinkalive;
-.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
+.float redalive_stat = _STAT(REDALIVE);
+.float bluealive_stat = _STAT(BLUEALIVE);
+.float yellowalive_stat = _STAT(YELLOWALIVE);
+.float pinkalive_stat = _STAT(PINKALIVE);
#endif
round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart);
round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
- addstat(STAT_REDALIVE, AS_INT, redalive_stat);
- addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
- addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
- addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
EliminatedPlayers_Init(ca_isEliminated);
}
#define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b))
// networked flag statuses
-.int ctf_flagstatus;
+.int ctf_flagstatus = _STAT(CTF_FLAGSTATUS);
#endif
const int CTF_RED_FLAG_TAKEN = 1;
ctf_CheckFlagReturn(self, RETURN_SPEEDRUN);
setself(self.owner);
- self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set
- ImpulseCommands();
+ self.impulse = CHIMPULSE_SPEEDRUN.impulse; // move the player back to the waypoint they set
+ ImpulseCommands(self);
setself(this);
}
if(autocvar_g_ctf_stalemate)
// if no teams are found, spawn defaults
if(find(world, classname, "ctf_team") == world)
{
- LOG_INFO("No ""ctf_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"ctf_team\" entities found on this map, creating them anyway.\n");
ctf_SpawnTeam("Red", NUM_TEAM_1 - 1);
ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1);
if(ctf_teams >= 3)
ctf_captureshield_max_ratio = autocvar_g_ctf_shield_max_ratio;
ctf_captureshield_force = autocvar_g_ctf_shield_force;
- addstat(STAT_CTF_FLAGSTATUS, AS_INT, ctf_flagstatus);
-
InitializeEntity(world, ctf_DelayedInit, INITPRIO_GAMETYPE);
}
{
if (time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
- cts_Initialize();
g_race_qualifying = true;
independent_players = 1;
- SetLimits(0, 0, 0, -1);
+ SetLimits(0, 0, -1, -1);
+
+ cts_Initialize();
}
MUTATOR_ONROLLBACK_OR_REMOVE
return false;
}
-MUTATOR_HOOKFUNCTION(cts, PlayerPreThink)
-{SELFPARAM();
- if(IS_SPEC(self) || IS_OBSERVER(self))
- if(g_race_qualifying)
- if(msg_entity.enemy.race_laptime)
- race_SendNextCheckpoint(msg_entity.enemy, 1);
-
- return false;
-}
-
MUTATOR_HOOKFUNCTION(cts, ClientConnect)
{SELFPARAM();
race_PreparePlayer();
const float SP_DOM_CAPS = 4;
// pps: points per second
-.float dom_total_pps;
-.float dom_pps_red;
-.float dom_pps_blue;
-.float dom_pps_yellow;
-.float dom_pps_pink;
+.float dom_total_pps = _STAT(DOM_TOTAL_PPS);
+.float dom_pps_red = _STAT(DOM_PPS_RED);
+.float dom_pps_blue = _STAT(DOM_PPS_BLUE);
+.float dom_pps_yellow = _STAT(DOM_PPS_YELLOW);
+.float dom_pps_pink = _STAT(DOM_PPS_PINK);
float total_pps;
float pps_red;
float pps_blue;
// if no teams are found, spawn defaults
if(find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
{
- LOG_INFO("No ""dom_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"dom_team\" entities found on this map, creating them anyway.\n");
domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
dom_spawnteams(domination_teams);
}
CheckAllowedTeams(world);
domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
- addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
- addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
- addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
- if(domination_teams >= 3) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
- if(domination_teams >= 4) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
-
domination_roundbased = autocvar_g_domination_roundbased;
ScoreRules_dom(domination_teams);
round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, func_null);
round_handler_Init(5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
- addstat(STAT_REDALIVE, AS_INT, redalive_stat);
- addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
- addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
- addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
EliminatedPlayers_Init(freezetag_isEliminated);
}
{
if (time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
- race_Initialize();
rc_SetLimits();
+ race_Initialize();
}
MUTATOR_ONROLLBACK_OR_REMOVE
return false;
}
-MUTATOR_HOOKFUNCTION(rc, PlayerPreThink)
-{SELFPARAM();
- if(IS_SPEC(self) || IS_OBSERVER(self))
- if(g_race_qualifying)
- if(msg_entity.enemy.race_laptime)
- race_SendNextCheckpoint(msg_entity.enemy, 1);
-
- return false;
-}
-
MUTATOR_HOOKFUNCTION(rc, ClientConnect)
{SELFPARAM();
race_PreparePlayer();
// if no teams are found, spawn defaults
if(find(world, classname, "tdm_team") == world)
{
- LOG_INFO("No ""tdm_team"" entities found on this map, creating them anyway.\n");
+ LOG_INFO("No \"tdm_team\" entities found on this map, creating them anyway.\n");
int numteams = min(4, autocvar_g_tdm_teams_override);
PLAYERDEMO_FIELDS(playerdemo_read_)
{
time = this.playerdemo_time;
- WITH(entity, this, this, PlayerPreThink());
+ WITH(entity, self, this, PlayerPreThink());
// not running physics though... this is just so we can run weapon stuff
- WITH(entity, this, this, PlayerPostThink());
+ WITH(entity, self, this, PlayerPostThink());
}
this.playerdemo_time = stof(fgets(this.playerdemo_fh));
if(this.playerdemo_time == 0)
#include "weapons/weaponstats.qc"
#include "weapons/weaponsystem.qc"
+#include "../common/anim.qc"
#include "../common/animdecide.qc"
#include "../common/campaign_file.qc"
#include "../common/campaign_setup.qc"
#include "../common/deathtypes/all.qc"
#include "../common/effects/all.qc"
#include "../common/gamemodes/all.qc"
+#include "../common/impulses/all.qc"
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
#include "../common/turrets/all.qc"
#include "../lib/warpzone/common.qh"
#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
+void race_InitSpectator()
+{
+ if(g_race_qualifying)
+ if(msg_entity.enemy.race_laptime)
+ race_SendNextCheckpoint(msg_entity.enemy, 1);
+}
+
void W_Porto_Fail(float failhard);
float race_readTime(string map, float pos)
void race_RetractPlayer();
+void race_InitSpectator();
+
#endif
if(fullstatus)
{
s = GetPlayerScoreString(p, 1);
- if(IS_REAL_CLIENT(p))
- s = strcat(s, ":human");
- else
- s = strcat(s, ":bot");
+ s = strcat(s, IS_REAL_CLIENT(p) ? ":human" : ":bot");
+ ret_string = string_null;
if(!IS_PLAYER(p) && !MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
s = strcat(s, ":spectator");
- s = strcat(s, ret_string);
+ if (ret_string) s = strcat(s, ret_string);
}
else
{
- if(IS_PLAYER(p) || MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
+ ret_string = string_null;
+ if (IS_PLAYER(p) || MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
s = GetPlayerScoreString(p, 2);
else
s = "-666";
- s = strcat(s, ret_string);
+ if (ret_string) s = strcat(s, ret_string);
}
if(p.clientstatus)
.float lastground;
.int state;
-void CreatureFrame ()
-{SELFPARAM();
- float dm;
-
- for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
+void CreatureFrame_hotliquids(entity this)
+{
+ if (this.dmgtime < time)
{
- setself(e);
- if (self.movetype == MOVETYPE_NOCLIP) { continue; }
-
- float vehic = IS_VEHICLE(self);
- float projectile = (self.flags & FL_PROJECTILE);
- float monster = IS_MONSTER(self);
+ this.dmgtime = time + autocvar_g_balance_contents_damagerate;
- if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+ if (this.flags & FL_PROJECTILE)
{
- if (!(self.flags & FL_INWATER))
- {
- self.flags |= FL_INWATER;
- self.dmgtime = 0;
- }
-
- if(!vehic && !projectile && !monster) // vehicles, monsters and projectiles don't drown
+ if (this.watertype == CONTENT_LAVA)
+ Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+ else if (this.watertype == CONTENT_SLIME)
+ Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
+ }
+ else
+ {
+ if (this.watertype == CONTENT_LAVA)
{
- if (self.waterlevel != WATERLEVEL_SUBMERGED)
+ if (this.watersound_finished < time)
{
- if(self.air_finished < time)
- PlayerSound(playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- self.air_finished = time + autocvar_g_balance_contents_drowndelay;
- self.dmg = 2;
- }
- else if (self.air_finished < time)
- { // drown!
- if (!self.deadflag)
- if (self.pain_finished < time)
- {
- Damage (self, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, self.origin, '0 0 0');
- self.pain_finished = time + 0.5;
- }
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
}
+ Damage (this, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+ if(autocvar_g_balance_contents_playerdamage_lava_burn)
+ Fire_AddDamage(this, world, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
}
-
- if (self.dmgtime < time)
+ else if (this.watertype == CONTENT_SLIME)
{
- self.dmgtime = time + autocvar_g_balance_contents_damagerate;
-
- if (projectile)
- {
- if (self.watertype == CONTENT_LAVA)
- {
- Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
- }
- else if (self.watertype == CONTENT_SLIME)
- {
- Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
- }
- }
- else
+ if (this.watersound_finished < time)
{
- if (self.watertype == CONTENT_LAVA)
- {
- if (self.watersound_finished < time)
- {
- self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
- }
- Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
- if(autocvar_g_balance_contents_playerdamage_lava_burn)
- Fire_AddDamage(self, world, autocvar_g_balance_contents_playerdamage_lava_burn * self.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * self.waterlevel, DEATH_LAVA.m_id);
- }
- else if (self.watertype == CONTENT_SLIME)
- {
- if (self.watersound_finished < time)
- {
- self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
- }
- Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
- }
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
}
+ Damage (this, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
}
}
- else
+ }
+}
+
+void CreatureFrame_Liquids(entity this)
+{
+ if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+ {
+ if (!(this.flags & FL_INWATER))
{
- if (self.flags & FL_INWATER)
- {
- // play leave water sound
- self.flags &= ~FL_INWATER;
- self.dmgtime = 0;
- }
- self.air_finished = time + 12;
- self.dmg = 2;
+ this.flags |= FL_INWATER;
+ this.dmgtime = 0;
}
- if(!vehic && !projectile) // vehicles don't get falling damage
+ CreatureFrame_hotliquids(this);
+ }
+ else
+ {
+ if (this.flags & FL_INWATER)
{
- // check for falling damage
- float velocity_len = vlen(self.velocity);
- if(!self.hook.state)
- {
- dm = vlen(self.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
- if (self.deadflag)
- dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
- else
- dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
- if (dm > 0)
- Damage (self, world, world, dm, DEATH_FALL.m_id, self.origin, '0 0 0');
- }
+ // play leave water sound
+ this.flags &= ~FL_INWATER;
+ this.dmgtime = 0;
+ }
+ this.air_finished = time + 12;
+ this.dmg = 2;
+ }
+}
- if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
- Damage (self, world, world, 100000, DEATH_SHOOTING_STAR.m_id, self.origin, '0 0 0');
- // play stupid sounds
- if (g_footsteps)
- if (!gameover)
- if (self.flags & FL_ONGROUND)
- if (!self.crouch)
- if (velocity_len > autocvar_sv_maxspeed * 0.6)
- if (!self.deadflag)
- if (time < self.lastground + 0.2)
- {
- if((time > self.nextstep) || (time < (self.nextstep - 10.0)))
- {
- self.nextstep = time + 0.3 + random() * 0.1;
- trace_dphitq3surfaceflags = 0;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
- /*
- if(trace_fraction == 1)
- dprint("nohit\n");
- else
- dprint(ftos(trace_dphitq3surfaceflags), "\n");
- */
- if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
- {
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
- GlobalSound(GS_STEP_METAL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- else
- GlobalSound(GS_STEP, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- }
- }
- }
+void CreatureFrame_FallDamage(entity this)
+{
+ if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
+ {
+ // check for falling damage
+ float velocity_len = vlen(this.velocity);
+ if(!this.hook.state)
+ {
+ float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+ if (this.deadflag)
+ dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+ else
+ dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+ if (dm > 0)
+ Damage (this, world, world, dm, DEATH_FALL.m_id, this.origin, '0 0 0');
}
- self.oldvelocity = self.velocity;
+ if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+ Damage (this, world, world, 100000, DEATH_SHOOTING_STAR.m_id, this.origin, '0 0 0');
+ }
+}
+
+void CreatureFrame_All()
+{
+ for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
+ {
+ if (e.movetype == MOVETYPE_NOCLIP) { continue; }
+
+ CreatureFrame_Liquids(e);
+ CreatureFrame_FallDamage(e);
+
+ e.oldvelocity = e.velocity;
}
- setself(this);
}
game_delay_last = game_delay;
- CreatureFrame();
+ CreatureFrame_All();
CheckRules_World();
// if in warmup stage and limit for warmup is hit start match
bot_serverframe();
anticheat_startframe();
MUTATOR_CALLHOOK(SV_StartFrame);
+ {
+ entity e;
+ FOR_EACH_CLIENT(e)
+ {
+ GlobalStats_update(e);
+ }
+ }
}
.vector originjitter;
MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
do {
{
- entity wi = get_weaponinfo(self.weapon);
+ entity wi = Weapons_from(self.weapon);
if (wi.m_id) {
entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
wp.wp_extra = wi.m_id;
if (player.switchweapon == w_getbestweapon(player))
_switchweapon = true;
- if (!(player.weapons & WepSet_FromWeapon(player.switchweapon)))
+ if (!(player.weapons & WepSet_FromWeapon(Weapons_from(player.switchweapon))))
_switchweapon = true;
pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
{
pickedup = true;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- if(it & WepSet_FromWeapon(i))
+ if(it & WepSet_FromWeapon(Weapons_from(i)))
{
W_DropEvent(wr_pickup, player, i, item);
W_GiveWeapon(player, i);
// crude hack to enforce switching weapons
if(g_cts && item.itemdef.instanceOfWeaponPickup)
{
- W_SwitchWeapon_Force(player, item.weapon);
+ W_SwitchWeapon_Force(player, Weapons_from(item.weapon));
return 1;
}
if (_switchweapon)
if (player.switchweapon != w_getbestweapon(player))
- W_SwitchWeapon_Force(player, w_getbestweapon(player));
+ W_SwitchWeapon_Force(player, Weapons_from(w_getbestweapon(player)));
return 1;
}
// Detect needed ammo
for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
{
- wi = get_weaponinfo(i);
+ wi = Weapons_from(i);
if (!(player.weapons & (wi.m_wepset)))
continue;
}
if(weaponid)
- this.weapons = WepSet_FromWeapon(weaponid);
+ this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
this.flags = FL_ITEM | itemflags;
this.is_item = true;
}
- weaponsInMap |= WepSet_FromWeapon(weaponid);
+ weaponsInMap |= WepSet_FromWeapon(Weapons_from(weaponid));
precache_model(this.model);
precache_sound(this.item_pickupsound);
{
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
s = W_UndeprecateName(argv(i));
if(s == e.netname)
{
self.weapons |= (e.m_wepset);
if(self.spawnflags == 0 || self.spawnflags == 2) {
- Weapon w = get_weaponinfo(e.weapon);
+ Weapon w = Weapons_from(e.weapon);
w.wr_init(w);
}
break;
if(self.armorvalue != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "armor");
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if(e.weapon)
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & (e.m_wepset)), e.netname);
}
{
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if(argv(i) == e.netname)
{
- Weapon w = get_weaponinfo(e.weapon);
+ Weapon w = Weapons_from(e.weapon);
w.wr_init(w);
break;
}
float GiveWeapon(entity e, float wpn, float op, float val)
{
WepSet v0, v1;
- WepSet s = WepSet_FromWeapon(wpn);
+ WepSet s = WepSet_FromWeapon(Weapons_from(wpn));
v0 = (e.weapons & s);
switch(op)
{
case "allweapons":
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- wi = get_weaponinfo(j);
+ wi = Weapons_from(j);
if(wi.weapon)
if (!(wi.spawnflags & WEP_FLAG_MUTATORBLOCKED))
got += GiveWeapon(e, j, op, val);
default:
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- wi = get_weaponinfo(j);
+ wi = Weapons_from(j);
if(cmd == wi.netname)
{
got += GiveWeapon(e, j, op, val);
POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND(ITEMPICKUP), string_null);
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- wi = get_weaponinfo(j);
+ wi = Weapons_from(j);
if(wi.weapon)
{
- POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
+ POSTGIVE_WEAPON(e, Weapons_from(j), SND(WEAPONPICKUP), string_null);
if (!(save_weapons & (wi.m_wepset)))
if(e.weapons & (wi.m_wepset)) {
- Weapon w = get_weaponinfo(wi.weapon);
+ Weapon w = Weapons_from(wi.weapon);
w.wr_init(w);
}
}
else
e.superweapons_finished += time;
- if (!(e.weapons & WepSet_FromWeapon(e.switchweapon)))
+ if (!(e.weapons & WepSet_FromWeapon(Weapons_from(e.switchweapon))))
_switchweapon = true;
if(_switchweapon)
- W_SwitchWeapon_Force(e, w_getbestweapon(e));
+ W_SwitchWeapon_Force(e, Weapons_from(w_getbestweapon(e)));
return got;
}
if(!IS_CLIENT(self))
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_CONNECTING, self.netname);
+ MUTATOR_CALLHOOK(Player_ChangeTeam, self, steam, dteam);
+
SetPlayerTeam(self, dteam, steam, !IS_CLIENT(self));
if(IS_PLAYER(self) && steam != dteam)
}
// update accuracy stats
-.float hit_time;
+//.float hit_time;
.float fired_time;
void accuracy_add(entity this, int w, int fired, int hit)
if (!wep)
return;
- e.weapons |= WepSet_FromWeapon(wep);
+ e.weapons |= WepSet_FromWeapon(Weapons_from(wep));
setself(e);
WriteByte(MSG_ONE, type);
}
-float client_hasweapon(entity cl, float wpn, float andammo, float complain)
-{SELFPARAM();
+bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain)
+{
float f;
- if(time < self.hasweapon_complain_spam)
+ if (time < cl.hasweapon_complain_spam)
complain = 0;
// ignore hook button when using other offhand equipment
if (cl.offhand != OFFHAND_HOOK)
- if (wpn == WEP_HOOK.m_id && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
+ if (wpn == WEP_HOOK && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
complain = 0;
- if(complain)
- self.hasweapon_complain_spam = time + 0.2;
+ if (complain)
+ cl.hasweapon_complain_spam = time + 0.2;
- if (wpn < WEP_FIRST || wpn > WEP_LAST)
+ if (wpn == WEP_Null)
{
if (complain)
- sprint(self, "Invalid weapon\n");
+ sprint(cl, "Invalid weapon\n");
return false;
}
if (cl.weapons & WepSet_FromWeapon(wpn))
}
else
{
- setself(cl);
- Weapon w = get_weaponinfo(wpn);
- f = w.wr_checkammo1(w) + w.wr_checkammo2(w);
+ WITH(entity, self, cl, f = wpn.wr_checkammo1(wpn) + wpn.wr_checkammo2(wpn));
// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
entity mine;
- if(wpn == WEP_MINE_LAYER.m_id)
- for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+ if(wpn == WEP_MINE_LAYER)
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == cl)
f = 1;
- setself(this);
}
if (!f)
{
if(IS_REAL_CLIENT(cl))
{
play2(cl, SND(UNAVAILABLE));
- Send_WeaponComplain (cl, wpn, 0);
+ Send_WeaponComplain (cl, wpn.m_id, 0);
}
return false;
}
// Report Proper Weapon Status / Modified Weapon Ownership Message
if (weaponsInMap & WepSet_FromWeapon(wpn))
{
- Send_WeaponComplain(cl, wpn, 1);
+ Send_WeaponComplain(cl, wpn.m_id, 1);
if(autocvar_g_showweaponspawns)
{
entity e;
- for(e = world; (e = findfloat(e, weapon, wpn)); )
+ for(e = world; (e = findfloat(e, weapon, wpn.m_id)); )
{
if(e.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
continue;
WP_Weapon,
1, 0,
world, e.origin + ('0 0 1' * e.maxs.z) * 1.2,
- self, 0,
+ cl, 0,
world, enemy,
0,
RADARICON_NONE
);
- wp.wp_extra = wpn;
+ wp.wp_extra = wpn.m_id;
}
}
}
else
{
- Send_WeaponComplain (cl, wpn, 2);
+ Send_WeaponComplain (cl, wpn.m_id, 2);
}
play2(cl, SND(UNAVAILABLE));
while(rest != "")
{
weaponwant = stof(car(rest)); rest = cdr(rest);
- wep = get_weaponinfo(weaponwant);
+ wep = Weapons_from(weaponwant);
wepset = wep.m_wepset;
if(imp >= 0)
if(wep.impulse != imp)
continue;
- float i, have_other = false;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- Weapon e = get_weaponinfo(i);
+ bool have_other = false;
+ FOREACH(Weapons, it != WEP_Null, {
if(i != weaponwant)
- if(e.impulse == imp || imp < 0)
- if((pl.weapons & (e.m_wepset)) || (weaponsInMap & (e.m_wepset)))
+ if(it.impulse == imp || imp < 0)
+ if((pl.weapons & (it.m_wepset)) || (weaponsInMap & (it.m_wepset)))
have_other = true;
- }
+ });
// skip weapons we don't own that aren't normal and aren't in the map
if(!(pl.weapons & wepset))
++c;
- if(!skipmissing || client_hasweapon(pl, weaponwant, true, false))
+ if(!skipmissing || client_hasweapon(pl, wep, true, false))
{
if(switchtonext)
return weaponwant;
while(rest != "")
{
weaponwant = stof(car(rest)); rest = cdr(rest);
- wep = get_weaponinfo(weaponwant);
+ wep = Weapons_from(weaponwant);
wepset = wep.m_wepset;
if(imp >= 0)
if(wep.impulse != imp)
continue;
- float i, have_other = false;
- for(i = WEP_FIRST; i <= WEP_LAST; ++i)
- {
- Weapon w = get_weaponinfo(i);
+ bool have_other = false;
+ FOREACH(Weapons, it != WEP_Null, {
if(i != weaponwant)
- if(w.impulse == imp || imp < 0)
- if((pl.weapons & (w.m_wepset)) || (weaponsInMap & (w.m_wepset)))
+ if(it.impulse == imp || imp < 0)
+ if((pl.weapons & (it.m_wepset)) || (weaponsInMap & (it.m_wepset)))
have_other = true;
- }
+ });
// skip weapons we don't own that aren't normal and aren't in the map
if(!(pl.weapons & wepset))
--c;
if(c == 0)
{
- client_hasweapon(pl, weaponwant, true, true);
+ client_hasweapon(pl, wep, true, true);
break;
}
}
return 0;
}
-void W_SwitchWeapon_Force(entity e, float w)
+void W_SwitchWeapon_Force(entity e, Weapon wep)
{
+ int w = wep.m_id;
e.cnt = e.switchweapon;
e.switchweapon = w;
e.selectweapon = w;
{
// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
int ww;
- WepSet set = WepSet_FromWeapon(pl.weapon);
+ WepSet set = WepSet_FromWeapon(Weapons_from(pl.weapon));
if(pl.weapons & set)
{
pl.weapons &= ~set;
else
ww = w_getbestweapon(pl);
if(ww)
- W_SwitchWeapon_Force(pl, ww);
+ W_SwitchWeapon_Force(pl, Weapons_from(ww));
}
-void W_SwitchWeapon(float imp)
+void W_SwitchWeapon(Weapon w)
{SELFPARAM();
+ int imp = w.m_id;
if (self.switchweapon != imp)
{
- if (client_hasweapon(self, imp, true, true))
- W_SwitchWeapon_Force(self, imp);
+ if (client_hasweapon(self, w, true, true))
+ W_SwitchWeapon_Force(self, w);
else
self.selectweapon = imp; // update selectweapon ANYWAY
}
else if(!forbidWeaponUse(self)) {
- Weapon w = get_weaponinfo(self.weapon);
w.wr_reload(w);
}
}
float w;
w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, true);
if(w > 0)
- W_SwitchWeapon(w);
+ W_SwitchWeapon(Weapons_from(w));
}
void W_NextWeaponOnImpulse(float imp)
float w;
w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
if(w > 0)
- W_SwitchWeapon(w);
+ W_SwitchWeapon(Weapons_from(w));
}
// next weapon
// previously used if exists and has ammo, (second) best otherwise
void W_LastWeapon()
{SELFPARAM();
- if(client_hasweapon(self, self.cnt, true, false))
- W_SwitchWeapon(self.cnt);
+ Weapon wep = Weapons_from(self.cnt);
+ if(client_hasweapon(self, wep, true, false))
+ W_SwitchWeapon(wep);
else
W_SwitchToOtherWeapon(self);
}
void Send_WeaponComplain(entity e, float wpn, float type);
.float hasweapon_complain_spam;
-float client_hasweapon(entity cl, float wpn, float andammo, float complain);
+bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain);
.int weaponcomplainindex;
float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing);
#define w_getbestweapon(ent) W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true)
-void W_SwitchWeapon_Force(entity e, float w);
+void W_SwitchWeapon_Force(entity e, Weapon w);
// perform weapon to attack (weaponstate and attack_finished check is here)
void W_SwitchToOtherWeapon(entity pl);
-void W_SwitchWeapon(float imp);
+void W_SwitchWeapon(Weapon imp);
void W_CycleWeapon(string weaponorder, float dir);
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if(e.netname == s)
{
replacement = e.weaponreplace;
int j;
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if (e.netname == s)
{
entity replacement = spawn();
int j;
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- e = get_weaponinfo(j);
+ e = Weapons_from(j);
if (e.netname == s)
{
wpn = j;
}
}
- e = get_weaponinfo(wpn);
+ e = Weapons_from(wpn);
if (!this.respawntime)
{
- if (e.weapons & WEPSET_SUPERWEAPONS)
+ if (e.spawnflags & WEP_FLAG_SUPERWEAPON)
{
this.respawntime = g_pickup_respawntime_superweapon;
this.respawntimejitter = g_pickup_respawntimejitter_superweapon;
}
}
- if (e.weapons & WEPSET_SUPERWEAPONS)
+ if (e.spawnflags & WEP_FLAG_SUPERWEAPON)
if (!this.superweapons_finished)
+ {
this.superweapons_finished = autocvar_g_balance_superweapons_time;
+ LOG_INFO("Setting it to ", ftos(this.superweapons_finished), " on ", e.mdl, "\n");
+ }
// if we don't already have ammo, give us some ammo
if (!this.(e.ammo_field))
{SELFPARAM();
float thisammo, i;
string s;
- Weapon info = get_weaponinfo(wpn);
+ Weapon info = Weapons_from(wpn);
var .int ammotype = info.ammo_field;
entity wep = new(droppedweapon);
W_DropEvent(wr_drop,own,wpn,wep);
- if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS)
+ if(WepSet_FromWeapon(Weapons_from(wpn)) & WEPSET_SUPERWEAPONS)
{
if(own.items & IT_UNLIMITED_SUPERWEAPONS)
{
float superweapons = 1;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- WepSet set = WepSet_FromWeapon(i);
+ WepSet set = WepSet_FromWeapon(Weapons_from(i));
if ((set & WEPSET_SUPERWEAPONS) && (own.weapons & set)) ++superweapons;
}
if(superweapons <= 1)
return false;
#if 0
- if(start_weapons & WepSet_FromWeapon(w))
+ if(start_weapons & WepSet_FromWeapon(Weapons_from(w)))
{
// start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo)
if(start_items & IT_UNLIMITED_WEAPON_AMMO)
return false;
- if((get_weaponinfo(w)).ammo_field == ammo_none)
+ if((Weapons_from(w)).ammo_field == ammo_none)
return false;
}
return true;
#else
- return (get_weaponinfo(w)).weaponthrowable;
+ return (Weapons_from(w)).weaponthrowable;
#endif
}
if(!W_IsWeaponThrowable(w))
return;
- WepSet set = WepSet_FromWeapon(w);
+ WepSet set = WepSet_FromWeapon(Weapons_from(w));
if(!(self.weapons & set)) return;
self.weapons &= ~set;
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ W_SwitchWeapon_Force(self, Weapons_from(w_getbestweapon(self)));
string a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
if(!a) return;
void SpawnThrownWeapon(vector org, float w)
{SELFPARAM();
- if(self.weapons & WepSet_FromWeapon(self.weapon))
+ if(self.weapons & WepSet_FromWeapon(Weapons_from(self.weapon)))
if(W_IsWeaponThrowable(self.weapon))
W_ThrowNewWeapon(self, self.weapon, false, org, randomvec() * 125 + '0 0 200');
}
#include "../../common/weapons/all.qh"
#include "../../lib/csqcmodel/sv_model.qh"
-vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
-{
- switch (algn)
- {
- default: case 3: break; // right alignment
- case 4: vecs.y = -vecs.y;
- break; // left
- case 1: case 2: vecs.y = 0;
- vecs.z -= 2;
- break; // center
- }
-
- return vecs;
-}
-
-vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
-{
- string s;
-
- if (visual)
- {
- vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
- }
- else if (autocvar_g_shootfromeye)
- {
- vecs.y = vecs.z = 0;
- }
- else if (autocvar_g_shootfromcenter)
- {
- vecs.y = 0;
- vecs.z -= 2;
- }
- else if ((s = autocvar_g_shootfromfixedorigin) != "")
- {
- vector v = stov(s);
- if (y_is_right) v.y = -v.y;
- if (v.x != 0) vecs.x = v.x;
- vecs.y = v.y;
- vecs.z = v.z;
- }
- else // just do the same as top
- {
- vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
- }
-
- return vecs;
-}
-
-vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn)
-{
- return shotorg_adjust_values(vecs, y_is_right, visual, algn);
-}
-
.int state;
.float weapon_frametime;
}
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
- .entity weaponentity, int fire) func);
-
bool CL_Weaponentity_CustomizeEntityForClient()
{
SELFPARAM();
return true;
}
-/*
- * supported formats:
- *
- * 1. simple animated model, muzzle flash handling on h_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * weapon = attachment for v_tuba.md3
- * v_tuba.md3 - first and third person model
- * g_tuba.md3 - pickup model
- *
- * 2. simple animated model, muzzle flash handling on v_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- * tags:
- * weapon = attachment for v_tuba.md3
- * v_tuba.md3 - first and third person model
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * g_tuba.md3 - pickup model
- *
- * 3. fully animated model, muzzle flash handling on h_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
- * v_tuba.md3 - third person model
- * g_tuba.md3 - pickup model
- *
- * 4. fully animated model, muzzle flash handling on v_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- * tags:
- * shot = muzzle end (shot origin)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * v_tuba.md3 - third person model
- * tags:
- * shot = muzzle end (for muzzle flashes)
- * g_tuba.md3 - pickup model
- */
-
-// writes:
-// this.origin, this.angles
-// this.weaponentity
-// this.movedir, this.view_ofs
-// attachment stuff
-// anim stuff
-// to free:
-// call again with ""
-// remove the ent
-void CL_WeaponEntity_SetModel(entity this, .entity weaponentity, string name)
-{
- if (name != "")
- {
- // if there is a child entity, hide it until we're sure we use it
- if (this.(weaponentity)) this.(weaponentity).model = "";
- _setmodel(this, W_Model(strcat("v_", name, ".md3")));
- int v_shot_idx = gettagindex(this, "shot"); // used later
- if (!v_shot_idx) v_shot_idx = gettagindex(this, "tag_shot");
-
- _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
- // preset some defaults that work great for renamed zym files (which don't need an animinfo)
- this.anim_fire1 = animfixfps(this, '0 1 0.01', '0 0 0');
- this.anim_fire2 = animfixfps(this, '1 1 0.01', '0 0 0');
- this.anim_idle = animfixfps(this, '2 1 0.01', '0 0 0');
- this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
-
- // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
- // if we don't, this is a "real" animated model
- if (gettagindex(this, "weapon"))
- {
- if (!this.(weaponentity)) this.(weaponentity) = new(weaponentity);
- _setmodel(this.(weaponentity), W_Model(strcat("v_", name, ".md3")));
- setattachment(this.(weaponentity), this, "weapon");
- }
- else if (gettagindex(this, "tag_weapon"))
- {
- if (!this.(weaponentity)) this.(weaponentity) = new(weaponentity);
- _setmodel(this.(weaponentity), W_Model(strcat("v_", name, ".md3")));
- setattachment(this.(weaponentity), this, "tag_weapon");
- }
- else
- {
- if (this.(weaponentity)) remove(this.(weaponentity));
- this.(weaponentity) = NULL;
- }
-
- setorigin(this, '0 0 0');
- this.angles = '0 0 0';
- this.frame = 0;
- this.viewmodelforclient = NULL;
-
- float idx;
-
- if (v_shot_idx) // v_ model attached to invisible h_ model
- {
- this.movedir = gettaginfo(this.(weaponentity), v_shot_idx);
- }
- else
- {
- idx = gettagindex(this, "shot");
- if (!idx) idx = gettagindex(this, "tag_shot");
- if (idx)
- {
- this.movedir = gettaginfo(this, idx);
- }
- else
- {
- LOG_INFO("WARNING: weapon model ", this.model,
- " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
- this.movedir = '0 0 0';
- }
- }
-
- if (this.(weaponentity)) // v_ model attached to invisible h_ model
- {
- idx = gettagindex(this.(weaponentity), "shell");
- if (!idx) idx = gettagindex(this.(weaponentity), "tag_shell");
- if (idx) this.spawnorigin = gettaginfo(this.(weaponentity), idx);
- }
- else
- {
- idx = 0;
- }
- if (!idx)
- {
- idx = gettagindex(this, "shell");
- if (!idx) idx = gettagindex(this, "tag_shell");
- if (idx)
- {
- this.spawnorigin = gettaginfo(this, idx);
- }
- else
- {
- LOG_INFO("WARNING: weapon model ", this.model,
- " does not support the 'shell' tag, will display casings wrong\n");
- this.spawnorigin = this.movedir;
- }
- }
-
- if (v_shot_idx)
- {
- this.oldorigin = '0 0 0'; // use regular attachment
- }
- else
- {
- if (this.(weaponentity))
- {
- idx = gettagindex(this, "weapon");
- if (!idx) idx = gettagindex(this, "tag_weapon");
- }
- else
- {
- idx = gettagindex(this, "handle");
- if (!idx) idx = gettagindex(this, "tag_handle");
- }
- if (idx)
- {
- this.oldorigin = this.movedir - gettaginfo(this, idx);
- }
- else
- {
- LOG_INFO("WARNING: weapon model ", this.model,
- " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
- this.oldorigin = '0 0 0'; // there is no way to recover from this
- }
- }
-
- this.viewmodelforclient = this.owner;
- }
- else
- {
- this.model = "";
- if (this.(weaponentity)) remove(this.(weaponentity));
- this.(weaponentity) = NULL;
- this.movedir = '0 0 0';
- this.spawnorigin = '0 0 0';
- this.oldorigin = '0 0 0';
- this.anim_fire1 = '0 1 0.01';
- this.anim_fire2 = '0 1 0.01';
- this.anim_idle = '0 1 0.01';
- this.anim_reload = '0 1 0.01';
- }
-
- this.view_ofs = '0 0 0';
-
- if (this.movedir.x >= 0)
- {
- vector v0 = this.movedir;
- this.movedir = shotorg_adjust(v0, false, false, this.owner.cvar_cl_gunalign);
- this.view_ofs = shotorg_adjust(v0, false, true, this.owner.cvar_cl_gunalign) - v0;
- }
- this.owner.stat_shotorg = compressShotOrigin(this.movedir);
- this.movedir = decompressShotOrigin(this.owner.stat_shotorg); // make them match perfectly
-
- this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount
-
- // check if an instant weapon switch occurred
- setorigin(this, this.view_ofs);
- // reset animstate now
- this.wframe = WFRAME_IDLE;
- setanim(this, this.anim_idle, true, false, true);
-}
-
-vector CL_Weapon_GetShotOrg(float wpn)
+vector CL_Weapon_GetShotOrg(int wpn)
{
entity wi = Weapons_from(wpn);
entity e = spawn();
- .entity weaponentity = weaponentities[0];
- CL_WeaponEntity_SetModel(e, weaponentity, wi.mdl);
+ CL_WeaponEntity_SetModel(e, wi.mdl);
vector ret = e.movedir;
- CL_WeaponEntity_SetModel(e, weaponentity, "");
+ CL_WeaponEntity_SetModel(e, "");
remove(e);
return ret;
}
..entity weaponentity_fld;
+.float m_alpha;
void CL_Weaponentity_Think()
{
.entity weaponentity = this.weaponentity_fld;
if (this.owner.(weaponentity) != this)
{
- if (this.(weaponentity)) remove(this.(weaponentity));
+ // owner has new gun; remove self
+ if (this.weaponchild) remove(this.weaponchild);
remove(this);
return;
}
if (this.owner.deadflag != DEAD_NO)
{
+ // owner died; disappear
this.model = "";
- if (this.(weaponentity)) this.(weaponentity).model = "";
+ if (this.weaponchild) this.weaponchild.model = "";
return;
}
- if (this.weaponname != this.owner.weaponname || this.dmg != this.owner.modelindex
+ if (this.weaponname != this.owner.weaponname
+ || this.dmg != this.owner.modelindex
|| this.deadflag != this.owner.deadflag)
{
+ // owner changed weapons; update appearance
this.weaponname = this.owner.weaponname;
this.dmg = this.owner.modelindex;
this.deadflag = this.owner.deadflag;
- CL_WeaponEntity_SetModel(this, weaponentity, this.owner.weaponname);
+ CL_WeaponEntity_SetModel(this, this.owner.weaponname);
}
- int tb = (this.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT));
- this.effects = this.owner.effects & EFMASK_CHEAP;
- this.effects &= ~EF_LOWPRECISION;
- this.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it
- this.effects &= ~EF_TELEPORT_BIT;
- this.effects &= ~EF_RESTARTANIM_BIT;
- this.effects |= tb;
- if (weaponentity != weaponentities[0]) this.effects |= EF_NODRAW;
+ this.alpha = -1; // TODO: don't render this entity at all
- if (this.owner.alpha == default_player_alpha) this.alpha = default_weapon_alpha;
- else if (this.owner.alpha != 0) this.alpha = this.owner.alpha;
- else this.alpha = 1;
+ if (this.owner.alpha == default_player_alpha) this.m_alpha = default_weapon_alpha;
+ else if (this.owner.alpha != 0) this.m_alpha = this.owner.alpha;
+ else this.m_alpha = 1;
- this.glowmod = this.owner.weaponentity_glowmod;
- this.colormap = this.owner.colormap;
- if (this.(weaponentity))
- {
- this.(weaponentity).effects = this.effects;
- this.(weaponentity).alpha = this.alpha;
- this.(weaponentity).colormap = this.colormap;
- this.(weaponentity).glowmod = this.glowmod;
- }
-
- this.angles = '0 0 0';
-
- float f = this.weapon_nextthink - time;
- if (this.state == WS_RAISE && !intermission_running)
- {
- entity newwep = Weapons_from(this.owner.switchweapon);
- f = f * g_weaponratefactor / max(f, newwep.switchdelay_raise);
- this.angles_x = -90 * f * f;
- }
- else if (this.state == WS_DROP && !intermission_running)
- {
- entity oldwep = Weapons_from(this.owner.weapon);
- f = 1 - f * g_weaponratefactor / max(f, oldwep.switchdelay_drop);
- this.angles_x = -90 * f * f;
- }
- else if (this.state == WS_CLEAR)
+ if (this.weaponchild)
{
- f = 1;
- this.angles_x = -90 * f * f;
+ this.weaponchild.alpha = this.alpha;
+ this.weaponchild.effects = this.effects;
}
}
}
// spawning weaponentity for client
-void CL_SpawnWeaponentity(entity e, .entity weaponentity)
+void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
{
- entity view = e.(weaponentity) = new(weaponentity);
+ entity view = actor.(weaponentity) = new(weaponentity);
make_pure(view);
view.solid = SOLID_NOT;
- view.owner = e;
+ view.owner = actor;
setmodel(view, MDL_Null); // precision set when changed
setorigin(view, '0 0 0');
- view.angles = '0 0 0';
- view.viewmodelforclient = e;
- view.flags = 0;
view.weaponentity_fld = weaponentity;
view.think = CL_Weaponentity_Think;
- view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
view.nextthink = time;
+ view.viewmodelforclient = actor;
+ view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
if (weaponentity == weaponentities[0])
{
- entity exterior = e.exteriorweaponentity = new(exteriorweaponentity);
+ entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
make_pure(exterior);
exterior.solid = SOLID_NOT;
- exterior.exteriorweaponentity = exterior;
- exterior.owner = e;
+ exterior.owner = actor;
setorigin(exterior, '0 0 0');
- exterior.angles = '0 0 0';
exterior.think = CL_ExteriorWeaponentity_Think;
exterior.nextthink = time;
if (mine.owner == actor) return false;
if (thiswep == WEP_SHOTGUN)
- if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false; // no clicking, just allow
+ if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false; // no clicking, just allow
if (thiswep == Weapons_from(actor.switchweapon) && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
{
return false;
}
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
+void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
+
+/**
+ * @param t defer thinking until time + t
+ * @param func next think function
+ */
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,
.entity weaponentity, int fire) func)
{
entity this = actor.(weaponentity);
fr = this.wframe;
restartanim = false;
}
- else if (fr == WFRAME_IDLE)
- {
- restartanim = false;
- }
else
{
- restartanim = true;
+ restartanim = fr != WFRAME_IDLE;
}
vector of = v_forward;
vector or = v_right;
vector ou = v_up;
+ vector a = '0 0 0';
if (this)
{
this.wframe = fr;
- vector a = '0 0 0';
if (fr == WFRAME_IDLE) a = this.anim_idle;
else if (fr == WFRAME_FIRE1) a = this.anim_fire1;
else if (fr == WFRAME_FIRE2) a = this.anim_fire2;
else // if (fr == WFRAME_RELOAD)
a = this.anim_reload;
a.z *= g_weaponratefactor;
- setanim(this, a, restartanim == false, restartanim, restartanim);
}
v_forward = of;
this.weapon_nextthink = time;
// dprint("reset weapon animation timer at ", ftos(time), "\n");
}
- this.weapon_nextthink = this.weapon_nextthink + t;
+ this.weapon_nextthink += t;
+ if (weaponentity == weaponentities[0]) STAT(WEAPON_NEXTTHINK, actor) = this.weapon_nextthink;
this.weapon_think = func;
// dprint("next ", ftos(this.weapon_nextthink), "\n");
+ if (this)
+ {
+ entity e;
+ FOR_EACH_CLIENT(e) if (e == actor || (IS_SPEC(e) && e.enemy == actor)) wframe_send(e, this, a, restartanim);
+ }
+
if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
{
- if ((actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id)
- && fr == WFRAME_FIRE2) animdecide_setaction(actor, ANIMACTION_MELEE, restartanim);
- else animdecide_setaction(actor, ANIMACTION_SHOOT, restartanim);
+ int act = (fr == WFRAME_FIRE2 && (actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id))
+ ? ANIMACTION_MELEE
+ : ANIMACTION_SHOOT
+ ;
+ animdecide_setaction(actor, act, restartanim);
}
- else
+ else if (actor.anim_upper_action == ANIMACTION_SHOOT || actor.anim_upper_action == ANIMACTION_MELEE)
{
- if (actor.anim_upper_action == ANIMACTION_SHOOT
- || actor.anim_upper_action == ANIMACTION_MELEE) actor.anim_upper_action = 0;
+ actor.anim_upper_action = 0;
}
}
void W_WeaponFrame(entity actor)
{
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+ .entity weaponentity = weaponentities[0]; // TODO: unhardcode
entity this = actor.(weaponentity);
if (frametime) actor.weapon_frametime = frametime;
- if (!this || actor.health < 1) return; // Dead player can't use weapons and injure impulse commands
+ if (!this || actor.health < 1) return; // Dead player can't use weapons and injure impulse commands
if (forbidWeaponUse(actor))
entity oldwep = Weapons_from(actor.weapon);
// set up weapon switch think in the future, and start drop anim
- if (
-#if INDEPENDENT_ATTACK_FINISHED
- true
-#else
- ATTACK_FINISHED(actor, slot) <= time + actor.weapon_frametime * 0.5
-#endif
- )
+ if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + actor.weapon_frametime * 0.5)
{
sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
this.state = WS_DROP;
// server framerate is very low and the weapon fire rate very high
for (int c = 0; c < W_TICSPERFRAME; ++c)
{
- if (w && !(actor.weapons & WepSet_FromWeapon(w)))
+ if (w && !(actor.weapons & WepSet_FromWeapon(Weapons_from(w))))
{
- if (actor.weapon == actor.switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ if (actor.weapon == actor.switchweapon) W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
w = 0;
}
}
else
{
- if (key_pressed && actor.switchweapon != WEP_HOOK.m_id && !actor.hook_switchweapon) W_SwitchWeapon(
- WEP_HOOK.m_id);
+ if (key_pressed && actor.switchweapon != WEP_HOOK.m_id && !actor.hook_switchweapon)
+ W_SwitchWeapon(WEP_HOOK);
actor.hook_switchweapon = key_pressed;
Weapon h = WEP_HOOK;
block_weapon = (actor.weapon == h.m_id && (actor.BUTTON_ATCK || key_pressed));
flash.owner = actor;
flash.angles_z = random() * 360;
- entity this = actor.(weaponentity);
- if (gettagindex(this, "shot")) setattachment(flash, this, "shot");
- else setattachment(flash, this, "tag_shot");
+ entity view = actor.(weaponentity);
+ entity exterior = actor.exteriorweaponentity;
+
+ if (gettagindex(view, "shot")) setattachment(flash, view, "shot");
+ else setattachment(flash, view, "tag_shot");
setorigin(flash, offset);
entity xflash = spawn();
flash.viewmodelforclient = actor;
- if (this.oldorigin.x > 0)
+ if (view.oldorigin.x > 0)
{
- setattachment(xflash, actor.exteriorweaponentity, "");
- setorigin(xflash, this.oldorigin + offset);
+ setattachment(xflash, exterior, "");
+ setorigin(xflash, view.oldorigin + offset);
}
else
{
- if (gettagindex(actor.exteriorweaponentity, "shot")) setattachment(xflash, actor.exteriorweaponentity, "shot");
- else setattachment(xflash, actor.exteriorweaponentity, "tag_shot");
+ if (gettagindex(exterior, "shot")) setattachment(xflash, exterior, "shot");
+ else setattachment(xflash, exterior, "tag_shot");
setorigin(xflash, offset);
}
}
#ifndef WEAPONSYSTEM_H
#define WEAPONSYSTEM_H
-.float wframe;
float internalteam;
float weaponswapping;
entity weapon_dropevent_item;
-// VorteX: static frame globals
-const float WFRAME_DONTCHANGE = -1;
-const float WFRAME_FIRE1 = 0;
-const float WFRAME_FIRE2 = 1;
-const float WFRAME_IDLE = 2;
-const float WFRAME_RELOAD = 3;
-
-vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn);
-
-vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
-
void CL_SpawnWeaponentity(entity e, .entity weaponentity);
vector CL_Weapon_GetShotOrg(float wpn);
void weapon_prepareattack_do(entity actor, .entity weaponentity, float secondary, float attacktime);
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
#endif