From: Rudolf Polzer Date: Fri, 11 Oct 2013 14:51:19 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/mirceakitsune/func_train_beizer_curve' X-Git-Tag: xonotic-v0.8.0~295 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=265b681e0fb49239df1bfc431a903f66244a3172 Merge remote-tracking branch 'origin/mirceakitsune/func_train_beizer_curve' Conflicts: qcsrc/server/t_plats.qc --- 265b681e0fb49239df1bfc431a903f66244a3172 diff --cc qcsrc/common/util.qc index 965431773e,08744b49f1..85efe4144a --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@@ -2492,241 -2415,26 +2492,263 @@@ float cubic_speedfunc_is_sane(float sta // (3, [0..3]) // (3.5, [0.2..2.3]) // (4, 1) + + /* + On another note: + inflection point is always at (2s + e - 3) / (3s + 3e - 6). + + s + e - 2 == 0: no inflection + + s + e > 2: + 0 < inflection < 1 if: + 0 < 2s + e - 3 < 3s + 3e - 6 + 2s + e > 3 and 2e + s > 3 + + s + e < 2: + 0 < inflection < 1 if: + 0 > 2s + e - 3 > 3s + 3e - 6 + 2s + e < 3 and 2e + s < 3 + + Therefore: there is an inflection point iff: + e outside (3 - s)/2 .. 3 - s*2 + + in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0) + */ } + +.float FindConnectedComponent_processing; +void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass) +{ + entity queue_start, queue_end; + + // we build a queue of to-be-processed entities. + // queue_start is the next entity to be checked for neighbors + // queue_end is the last entity added + + if(e.FindConnectedComponent_processing) + error("recursion or broken cleanup"); + + // start with a 1-element queue + queue_start = queue_end = e; + queue_end.fld = world; + queue_end.FindConnectedComponent_processing = 1; + + // for each queued item: + for(; queue_start; queue_start = queue_start.fld) + { + // find all neighbors of queue_start + entity t; + for(t = world; (t = nxt(t, queue_start, pass)); ) + { + if(t.FindConnectedComponent_processing) + continue; + if(iscon(t, queue_start, pass)) + { + // it is connected? ADD IT. It will look for neighbors soon too. + queue_end.fld = t; + queue_end = t; + queue_end.fld = world; + queue_end.FindConnectedComponent_processing = 1; + } + } + } + + // unmark + for(queue_start = e; queue_start; queue_start = queue_start.fld) + queue_start.FindConnectedComponent_processing = 0; +} + +// todo: this sucks, lets find a better way to do backtraces? +#ifndef MENUQC +void backtrace(string msg) +{ + float dev, war; + #ifdef SVQC + dev = autocvar_developer; + war = autocvar_prvm_backtraceforwarnings; + #else + dev = cvar("developer"); + war = cvar("prvm_backtraceforwarnings"); + #endif + cvar_set("developer", "1"); + cvar_set("prvm_backtraceforwarnings", "1"); + print("\n"); + print("--- CUT HERE ---\nWARNING: "); + print(msg); + print("\n"); + remove(world); // isn't there any better way to cause a backtrace? + print("\n--- CUT UNTIL HERE ---\n"); + cvar_set("developer", ftos(dev)); + cvar_set("prvm_backtraceforwarnings", ftos(war)); +} +#endif + +// color code replace, place inside of sprintf and parse the string +string CCR(string input) +{ + // See the autocvar declarations in util.qh for default values + + // foreground/normal colors + input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input); + input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input); + input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input); + input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input); + + // "kill" colors + input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input); + input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input); + input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input); + + // background colors + input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input); + input = strreplace("^N", "^7", input); // "none"-- reset to white... + return input; +} + +vector vec3(float x, float y, float z) +{ + vector v; + v_x = x; + v_y = y; + v_z = z; + return v; +} + +#ifndef MENUQC +vector animfixfps(entity e, vector a, vector b) +{ + // multi-frame anim: keep as-is + if(a_y == 1) + { + float dur; + dur = frameduration(e.modelindex, a_x); + if(dur <= 0 && b_y) + { + a = b; + dur = frameduration(e.modelindex, a_x); + } + if(dur > 0) + a_z = 1.0 / dur; + } + return a; +} +#endif + +#ifdef SVQC +void dedicated_print(string input) // print(), but only print if the server is not local +{ + if(server_is_dedicated) { print(input); } +} +#endif + +#ifndef MENUQC +float Announcer_PickNumber(float type, float num) +{ + switch(type) + { + case CNT_GAMESTART: + { + switch(num) + { + case 10: return ANNCE_NUM_GAMESTART_10; + case 9: return ANNCE_NUM_GAMESTART_9; + case 8: return ANNCE_NUM_GAMESTART_8; + case 7: return ANNCE_NUM_GAMESTART_7; + case 6: return ANNCE_NUM_GAMESTART_6; + case 5: return ANNCE_NUM_GAMESTART_5; + case 4: return ANNCE_NUM_GAMESTART_4; + case 3: return ANNCE_NUM_GAMESTART_3; + case 2: return ANNCE_NUM_GAMESTART_2; + case 1: return ANNCE_NUM_GAMESTART_1; + } + break; + } + case CNT_IDLE: + { + switch(num) + { + case 10: return ANNCE_NUM_IDLE_10; + case 9: return ANNCE_NUM_IDLE_9; + case 8: return ANNCE_NUM_IDLE_8; + case 7: return ANNCE_NUM_IDLE_7; + case 6: return ANNCE_NUM_IDLE_6; + case 5: return ANNCE_NUM_IDLE_5; + case 4: return ANNCE_NUM_IDLE_4; + case 3: return ANNCE_NUM_IDLE_3; + case 2: return ANNCE_NUM_IDLE_2; + case 1: return ANNCE_NUM_IDLE_1; + } + break; + } + case CNT_KILL: + { + switch(num) + { + case 10: return ANNCE_NUM_KILL_10; + case 9: return ANNCE_NUM_KILL_9; + case 8: return ANNCE_NUM_KILL_8; + case 7: return ANNCE_NUM_KILL_7; + case 6: return ANNCE_NUM_KILL_6; + case 5: return ANNCE_NUM_KILL_5; + case 4: return ANNCE_NUM_KILL_4; + case 3: return ANNCE_NUM_KILL_3; + case 2: return ANNCE_NUM_KILL_2; + case 1: return ANNCE_NUM_KILL_1; + } + break; + } + case CNT_RESPAWN: + { + switch(num) + { + case 10: return ANNCE_NUM_RESPAWN_10; + case 9: return ANNCE_NUM_RESPAWN_9; + case 8: return ANNCE_NUM_RESPAWN_8; + case 7: return ANNCE_NUM_RESPAWN_7; + case 6: return ANNCE_NUM_RESPAWN_6; + case 5: return ANNCE_NUM_RESPAWN_5; + case 4: return ANNCE_NUM_RESPAWN_4; + case 3: return ANNCE_NUM_RESPAWN_3; + case 2: return ANNCE_NUM_RESPAWN_2; + case 1: return ANNCE_NUM_RESPAWN_1; + } + break; + } + case CNT_ROUNDSTART: + { + switch(num) + { + case 10: return ANNCE_NUM_ROUNDSTART_10; + case 9: return ANNCE_NUM_ROUNDSTART_9; + case 8: return ANNCE_NUM_ROUNDSTART_8; + case 7: return ANNCE_NUM_ROUNDSTART_7; + case 6: return ANNCE_NUM_ROUNDSTART_6; + case 5: return ANNCE_NUM_ROUNDSTART_5; + case 4: return ANNCE_NUM_ROUNDSTART_4; + case 3: return ANNCE_NUM_ROUNDSTART_3; + case 2: return ANNCE_NUM_ROUNDSTART_2; + case 1: return ANNCE_NUM_ROUNDSTART_1; + } + break; + } + default: + { + switch(num) + { + case 10: return ANNCE_NUM_10; + case 9: return ANNCE_NUM_9; + case 8: return ANNCE_NUM_8; + case 7: return ANNCE_NUM_7; + case 6: return ANNCE_NUM_6; + case 5: return ANNCE_NUM_5; + case 4: return ANNCE_NUM_4; + case 3: return ANNCE_NUM_3; + case 2: return ANNCE_NUM_2; + case 1: return ANNCE_NUM_1; + } + break; + } + } + return NOTIF_ABORT; // abort sending if none of these numbers were right +} +#endif diff --cc qcsrc/server/g_subs.qc index 6444ffdb3c,f06f1ec745..96ccc267c4 --- a/qcsrc/server/g_subs.qc +++ b/qcsrc/server/g_subs.qc @@@ -1,6 -1,7 +1,5 @@@ -void SUB_Null() {} -float SUB_True() { return 1; } -float SUB_False() { return 0; } +void SUB_NullThink(void) { } - void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove; void() SUB_CalcMoveDone; void() SUB_CalcAngleMoveDone; //void() SUB_UseTargets; diff --cc qcsrc/server/t_plats.qc index 24da476d72,0c1bcdffb3..9ca98afb89 --- a/qcsrc/server/t_plats.qc +++ b/qcsrc/server/t_plats.qc @@@ -81,16 -86,16 +81,16 @@@ void plat_hit_bottom( void plat_go_down() { - sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM); self.state = 3; - SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom); } void plat_go_up() { - sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM); self.state = 4; - SUB_CalcMove (self.pos1, self.speed, plat_hit_top); + SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top); } void plat_center_touch() @@@ -273,23 -341,57 +336,57 @@@ void train_wait( void train_next() { - entity targ; + entity targ, cp; + vector cp_org; + targ = find(world, targetname, self.target); - self.enemy = targ; self.target = targ.target; + if (self.spawnflags & 1) + { + if(targ.curvetarget) + { + cp = find(world, targetname, targ.curvetarget); // get its second target (the control point) + cp_org = cp.origin - self.view_ofs; // no control point found, assume a straight line to the destination + } + else + cp = world; // no cp + } - if (!self.target) + if (self.target == "") objerror("train_next: no next target"); self.wait = targ.wait; if (!self.wait) self.wait = 0.1; + if(targ.platmovetype) + { + // this path_corner contains a movetype overrider, apply it + self.platmovetype_start = targ.platmovetype_start; + self.platmovetype_end = targ.platmovetype_end; + } + else + { + // this path_corner doesn't contain a movetype overrider, use the train's defaults + self.platmovetype_start = self.platmovetype_start_default; + self.platmovetype_end = self.platmovetype_end_default; + } + if (targ.speed) - SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait); + { + if (cp) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait); + else + SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait); + } else - SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait); + { + if (cp) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait); + else + SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait); + } if(self.noise != "") - sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } void func_train_find() @@@ -297,9 -399,9 +394,9 @@@ entity targ; targ = find(world, targetname, self.target); self.target = targ.target; - if (!self.target) + if (self.target == "") objerror("func_train_find: no next target"); - setorigin(self, targ.origin - self.mins); + setorigin(self, targ.origin - self.view_ofs); self.nextthink = self.ltime + 1; self.think = train_next; } @@@ -619,10 -734,10 +729,10 @@@ void button_fire( return; if (self.noise != "") - sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcMove (self.pos2, self.speed, button_wait); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait); } void button_reset() @@@ -861,9 -992,9 +971,9 @@@ void door_go_up( } if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcMove (self.pos2, self.speed, door_hit_top); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top); string oldmessage; oldmessage = self.message; @@@ -1162,9 -1293,9 +1272,9 @@@ void door_rotating_go_up( return; } if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcAngleMove (self.pos2, self.speed, door_rotating_hit_top); + SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top); string oldmessage; oldmessage = self.message; @@@ -1639,14 -1759,9 +1749,14 @@@ void fd_secret_use( self.dest1 = self.origin + v_right * (self.t_width * temp); self.dest2 = self.dest1 + v_forward * self.t_length; - SUB_CalcMove(self.dest1, self.speed, fd_secret_move1); + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1); if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); +} + +void fd_secret_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + fd_secret_use(); } // Wait after first movement... @@@ -1662,8 -1777,8 +1772,8 @@@ void fd_secret_move1( void fd_secret_move2() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.dest2, self.speed, fd_secret_move3); + SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3); } // Wait here until time to go back... @@@ -1682,8 -1797,8 +1792,8 @@@ void fd_secret_move3( void fd_secret_move4() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.dest1, self.speed, fd_secret_move5); + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5); } // Wait 1 second... @@@ -1698,8 -1813,8 +1808,8 @@@ void fd_secret_move5( void fd_secret_move6() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done); + SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done); } void fd_secret_done()