⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g_func.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:
			self^.nextthink := 0;
		end;

		if ((self^.flags and FL_TEAMSLAVE)=0) then
		begin
			if (self^.moveinfo.sound_end <> 0) then
				gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self^.moveinfo.sound_end, 1, ATTN_STATIC, 0);
			self^.s.sound := 0;
		end;
	end
	else
	begin
		train_next (self);
	end;

end;

procedure train_next (self:edict_p);
label again;
var
	ent:edict_p;
	dest:vec3_t;
	first:qboolean;
begin
	first := true;
again:
	if not Assigned(self^.target) then
	begin
//		gi.dprintf ('train_next: no next target\n');
		exit;
	end;

	ent := G_PickTarget (self^.target);
	if not Assigned(ent) then
	begin
		gi.dprintf ('train_next: bad target %s'#10, self^.target);
		exit;
	end;

	self^.target := ent^.target;

	// check for a teleport path_corner
	if (ent^.spawnflags and 1) <> 0 then
	begin
		if (not first) then
		begin
			gi.dprintf ('connected teleport path_corners, see %s at %s'#10, ent^.classname, vtos(ent^.s.origin));
			Exit;
		end;
		first := false;
		VectorSubtract (ent^.s.origin, self^.mins, self^.s.origin);
		VectorCopy (self^.s.origin, self^.s.old_origin);
		self^.s.event := EV_OTHER_TELEPORT;
		gi.linkentity (self);
		goto again;
	end;

	self^.moveinfo.wait := ent^.wait;
	self^.target_ent := ent;

	if ((self^.flags and FL_TEAMSLAVE)=0) then
	begin
		if (self^.moveinfo.sound_start) <> 0 then
			gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self^.moveinfo.sound_start, 1, ATTN_STATIC, 0);
		self^.s.sound := self^.moveinfo.sound_middle;
	end;

	VectorSubtract (ent^.s.origin, self^.mins, dest);
	self^.moveinfo.state := STATE_TOP;
	VectorCopy (self^.s.origin, self^.moveinfo.start_origin);
	VectorCopy (dest, self^.moveinfo.end_origin);
	Move_Calc (self, dest, train_wait);
	self^.spawnflags := self^.spawnflags or TRAIN_START_ON;
end;

procedure train_resume (self:edict_p);
var
	ent:edict_p;
	dest:vec3_t;
begin
	ent := self^.target_ent;

	VectorSubtract (ent^.s.origin, self^.mins, dest);
	self^.moveinfo.state := STATE_TOP;
	VectorCopy (self^.s.origin, self^.moveinfo.start_origin);
	VectorCopy (dest, self^.moveinfo.end_origin);
	Move_Calc (self, dest, train_wait);
	self^.spawnflags := self^.spawnflags or TRAIN_START_ON;
end;

procedure func_train_find (self:edict_p);
var
	ent:edict_p;
begin
	if not Assigned(self^.target) then
	begin
		gi.dprintf ('train_find: no target'#10);
		exit;
	end;
	ent := G_PickTarget (self^.target);
	if not Assigned(ent) then
	begin
		gi.dprintf ('train_find: target %s not found'#10, self^.target);
		exit;
	end;
	self^.target := ent^.target;

	VectorSubtract (ent^.s.origin, self^.mins, self^.s.origin);
	gi.linkentity (self);

	// if not triggered, start immediately
	if not Assigned(self^.targetname) then
		self^.spawnflags := self^.spawnflags or TRAIN_START_ON;

	if (self^.spawnflags and TRAIN_START_ON) <> 0 then
	begin
		self^.nextthink := level.time + FRAMETIME;
		self^.think := train_next;
		self^.activator := self;
	end;
end;

procedure train_use (self:edict_p; other:edict_p; activator:edict_p);
begin
	self^.activator := activator;

	if (self^.spawnflags and TRAIN_START_ON) <> 0 then
	begin
		if ((self^.spawnflags and TRAIN_TOGGLE)=0) then
			exit;
		self^.spawnflags := self^.spawnflags and (not TRAIN_START_ON);
		VectorClear (self^.velocity);
		self^.nextthink := 0;
	end
	else
	begin
		if assigned(self^.target_ent) then
			train_resume(self)
		else
			train_next(self);
	end;
end;

procedure SP_func_train (self:edict_p);
begin
	self^.movetype := MOVETYPE_PUSH;

	VectorClear (self^.s.angles);
	self^.blocked := train_blocked;
	if (self^.spawnflags and TRAIN_BLOCK_STOPS) <> 0 then
		self^.dmg := 0
	else
	begin
		if (self^.dmg=0) then
			self^.dmg := 100;
	end;
	self^.solid := SOLID_BSP;
	gi.setmodel (self, self^.model);

	if assigned(st.noise) then
		self^.moveinfo.sound_middle := gi.soundindex  (st.noise);

	if (self^.speed=0) then
		self^.speed := 100;

	self^.moveinfo.speed := self^.speed;
	self^.moveinfo.decel := self^.moveinfo.speed;
  self^.moveinfo.accel := self^.moveinfo.decel;

	self^.use := train_use;

	gi.linkentity (self);

	if Assigned(self^.target) then
	begin
		// start trains on the second frame, to make sure their targets have had
		// a chance to spawn
		self^.nextthink := level.time + FRAMETIME;
		self^.think := func_train_find;
	end
	else
	begin
		gi.dprintf ('func_train without a target at %s'#10, vtos(self^.absmin));
	end;
end;


(*QUAKED trigger_elevator (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
*)
procedure trigger_elevator_use (self:edict_p; other:edict_p; activator:edict_p); cdecl;
var
	target:edict_p;
begin
	if (self^.movetarget^.nextthink <> 0) then
	begin
  // next line was originaly commented - burnin
//		gi.dprintf('elevator busy\n');
		exit;
	end;

	if not Assigned(other^.pathtarget) then
	begin
		gi.dprintf('elevator used with no pathtarget'#10);
		exit;
	end;

	target := G_PickTarget (other^.pathtarget);
	if not Assigned(target) then
	begin
		gi.dprintf('elevator used with bad pathtarget: %s'#10, other^.pathtarget);
		exit;
	end;

	self^.movetarget^.target_ent := target;
	train_resume (self^.movetarget);
end;

procedure trigger_elevator_init (self:edict_p); cdecl;
begin
	if not Assigned(self^.target) then
	begin
		gi.dprintf('trigger_elevator has no target'#10);
		exit;
	end;
	self^.movetarget := G_PickTarget (self^.target);
	if not Assigned(self^.movetarget) then
	begin
		gi.dprintf('trigger_elevator unable to find target %s'#10, self^.target);
		exit;
	end;
	if (strcomp(self^.movetarget^.classname, 'func_train') <> 0) then
	begin
		gi.dprintf('trigger_elevator target %s is not a train'#10, self^.target);
		exit;
	end;

	self^.use := trigger_elevator_use;
	self^.svflags := SVF_NOCLIENT;

end;

procedure SP_trigger_elevator (self:edict_p);
begin
	self^.think := trigger_elevator_init;
	self^.nextthink := level.time + FRAMETIME;
end;


(*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
"wait"			base time between triggering all targets, default is 1
"random"		wait variance, default is 0

so, the basic time between firing is a random time between
(wait - random) and (wait + random)

"delay"			delay before first firing when turned on, default is 0

"pausetime"		additional delay used only the very first time
				and only if spawned with START_ON

These can used but not touched.
*)
procedure func_timer_think (self:edict_p); cdecl;
begin
	G_UseTargets (self, self^.activator);
	self^.nextthink := level.time + self^.wait + crandom * self^.random;
end;

procedure func_timer_use (self:edict_p; other:edict_p; activator:edict_p); cdecl;
begin
	self^.activator := activator;

	// if on, turn it off
	if (self^.nextthink <> 0) then
	begin
		self^.nextthink := 0;
		exit;
	end;

	// turn it on
	if (self^.delay <> 0) then
		self^.nextthink := level.time + self^.delay
	else
		func_timer_think (self);
end;

procedure SP_func_timer (self:edict_p);
begin
	if (self^.wait = 0) then
		self^.wait := 1.0;

	self^.use := func_timer_use;
	self^.think := func_timer_think;

	if (self^.random >= self^.wait) then
	begin
		self^.random := self^.wait - FRAMETIME;
		gi.dprintf('func_timer at %s has random >= wait'#10, vtos(self^.s.origin));
	end;

	if (self^.spawnflags and 1) <> 0 then
	begin
		self^.nextthink := level.time + 1.0 + st.pausetime + self^.delay + self^.wait + crandom() * self^.random;
		self^.activator := self;
	end;

	self^.svflags := SVF_NOCLIENT;
end;


(*QUAKED func_conveyor (0 .5 .8) ? START_ON TOGGLE
Conveyors are stationary brushes that move what's on them.
The brush should be have a surface with at least one current content enabled.
speed	default 100
*)

procedure func_conveyor_use (self:edict_p; other:edict_p; activator:edict_p); cdecl;
begin
	if (self^.spawnflags and 1) <> 0 then
	begin
		self^.speed := 0;
		self^.spawnflags := self^.spawnflags and (not 1);
	end
	else
	begin
		self^.speed := self^.count;
		self^.spawnflags := self^.spawnflags or 1;
	end;

	if (self^.spawnflags and 2) = 0 then
		self^.count := 0;
end;

procedure SP_func_conveyor (self:edict_p);
begin
	if (self^.speed = 0) then
		self^.speed := 100;

	if ((self^.spawnflags and 1)=0) then
	begin
		self^.count := trunc(self^.speed);
		self^.speed := 0;
	end;

	self^.use := func_conveyor_use;

	gi.setmodel (self, self^.model);
	self^.solid := SOLID_BSP;
	gi.linkentity (self);
end;


(*QUAKED func_door_secret (0 .5 .8) ? always_shoot 1st_left 1st_down
A secret door.  Slide back and then to the side.

open_once		doors never closes
1st_left		1st move is left of arrow
1st_down		1st move is down from arrow
always_shoot	door is shootebale even if targeted

"angle"		determines the direction
"dmg"		damage to inflic when blocked (default 2)
"wait"		how long to hold in the open position (default 5, -1 means hold)
*)

const SECRET_ALWAYS_SHOOT =	1;
const SECRET_1ST_LEFT	=	2;
const SECRET_1ST_DOWN	=	4;



procedure door_secret_use (self:edict_p; other:edict_p; activator:edict_p); cdecl;
begin
	// make sure we're not already moving
	if (VectorCompare(self^.s.origin, vec3_origin)=0) then
		exit;

	Move_Calc (self, self^.pos1, door_secret_move1);
	door_use_areaportals (self, true);
end;

procedure door_secret_move1 (self:edict_p);
begin
	self^.nextthink := level.time + 1.0;
	self^.think := door_secret_move2;
end;

procedure door_secret_move2 (self:edict_p);
begin
	Move_Calc (self, self^.pos2, door_secret_move3);
end;

procedure door_secret_move3 (self:edict_p);
begin
	if (self^.wait = -1) then
		exit;
	self^.nextthink := level.time + self^.wait;
	self^.think := door_secret_move4;
end;

procedure door_secret_move4 (self:edict_p);
begin
	Move_Calc (self, self^.pos1, door_secret_move5);
end;

procedure door_secret_move5 (self:edict_p);
begin
	self^.nextthink := level.time + 1.0;
	self^.think := door_secret_move6;
end;

procedure door_secret_move6 (self:edict_p);
begin
	Move_Calc (self, vec3_origin, door_secret_done);
end;

procedure door_secret_done (self:edict_p);
begin
	if (not assigned(self^.targetname) or (self^.spawnflags and SECRET_ALWAYS_SHOOT<>0)) then
	begin
		self^.health := 0;
		self^.takedamage := DAMAGE_YES;
	end;
	door_use_areaportals (self, false);
end;

procedure door_secret_blocked  (self:edict_p; other:edict_p); cdecl;
begin
	if ((other^.svflags and SVF_MONSTER=0) and (not Assigned(other^.client))) then
	begin
		// give it a chance to go away on it's own terms (like gibs)
		T_Damage (other, self, self, vec3_origin, other^.s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH);
		// if it's still there, nuke it
		if assigned(other) then
			BecomeExplosion1 (other);
		exit;
	end;

	if (level.time < self^.touch_debounce_time) then
		exit;
	self^.touch_debounce_time := level.time + 0.5;

	T_Damage (other, self, self, vec3_origin, other^.s.origin, vec3_origin, self^.dmg, 1, 0, MOD_CRUSH);
end;

procedure door_secret_die (self:edict_p;inflictor :edict_p; attacker:edict_p ; damage:integer; const point: vec3_t ); cdecl;
begin
	self^.takedamage := DAMAGE_NO;
	door_secret_use (self, attacker, attacker);
end;

procedure SP_func_door_secret (ent:edict_p);
var
	forwards, right, up:vec3_t;
	side:single;
	width:single;
	length:single;
begin
	ent^.moveinfo.sound_start := gi.soundindex  ('doors/dr1_strt.wav');
	ent^.moveinfo.sound_middle := gi.soundindex  ('doors/dr1_mid.wav');
	ent^.moveinfo.sound_end := gi.soundindex  ('doors/dr1_end.wav');

	ent^.movetype := MOVETYPE_PUSH;
	ent^.solid := SOLID_BSP;
	gi.setmodel (ent, ent^.model);

	ent^.blocked := door_secret_blocked;
	ent^.use := door_secret_use;

	if (not assigned(ent^.targetname) or (ent^.spawnflags and SECRET_ALWAYS_SHOOT<>0)) then
	begin
		ent^.health := 0;
		ent^.takedamage := DAMAGE_YES;
		ent^.die := door_secret_die;
	end;

	if (ent^.dmg = 0) then
		ent^.dmg := 2;

	if (ent^.wait=0) then
		ent^.wait := 5;

	ent^.moveinfo.accel := 50;
	ent^.moveinfo.decel := 50;
	ent^.moveinfo.speed := 50;

	// calculate positions
	AngleVectors (ent^.s.angles, @forwards, @right, @up);
	VectorClear (ent^.s.angles);
	side := 1.0 - (ent^.spawnflags and SECRET_1ST_LEFT);
	if (ent^.spawnflags and SECRET_1ST_DOWN) <> 0 then
		width := fabs(DotProduct(up, ent^.size))
	else
		width := fabs(DotProduct(right, ent^.size));
	length := fabs(DotProduct(forwards, ent^.size));
	if (ent^.spawnflags and SECRET_1ST_DOWN) <> 0 then
		VectorMA (ent^.s.origin, -1 * width, up, ent^.pos1)
	else
		VectorMA (ent^.s.origin, side * width, right, ent^.pos1);
	VectorMA (ent^.pos1, length, forwards, ent^.pos2);

	if (ent^.health) <> 0 then
	begin
		ent^.takedamage := DAMAGE_YES;
		ent^.die := door_killed;
		ent^.max_health := ent^.health;
	end
	else if assigned(ent^.targetname) and assigned(ent^._message) then
	begin
		gi.soundindex ('misc/talk.wav');
		ent^.touch := door_touch;
	end;

	ent^.classname := 'func_door';

	gi.linkentity (ent);
end;


(*QUAKED func_killbox (1 0 0) ?
Kills everything inside when fired, irrespective of protection.
*)
procedure use_killbox (self:edict_p; other:edict_p ;  activator:edict_p); cdecl;
begin
	KillBox (self);
end;

procedure SP_func_killbox (ent:edict_p);
begin
	gi.setmodel (ent, ent^.model);
	ent^.use := use_killbox;
	ent^.svflags := SVF_NOCLIENT;
end;


end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -