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

📄 g_func.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:
	door_use (self^.owner, other, other);
end;

procedure Think_CalcMoveSpeed (self:edict_p); cdecl;
var
	ent:edict_p;
	min:single;
	time:single;
	newspeed:single;
	ratio:single;
	dist:single;
begin
	if (self^.flags and FL_TEAMSLAVE<>0) then
		exit;		// only the team master does this

	// find the smallest distance any member of the team will be moving
	min := fabs(self^.moveinfo.distance);
  ent := self^.teamchain;
	while Assigned(ent) do
	begin
		dist := fabs(ent^.moveinfo.distance);
		if (dist < min) then
			min := dist;
		ent := ent^.teamchain;
	end;

	time := min / self^.moveinfo.speed;

	// adjust speeds so they will all complete at the same time
  ent := Self;
	while Assigned(ent) do
	begin
		newspeed := fabs(ent^.moveinfo.distance) / time;
		ratio := newspeed / ent^.moveinfo.speed;
		if (ent^.moveinfo.accel = ent^.moveinfo.speed) then
			ent^.moveinfo.accel := newspeed
		else
			ent^.moveinfo.accel := ent^.moveinfo.accel * ratio;
		if (ent^.moveinfo.decel = ent^.moveinfo.speed) then
			ent^.moveinfo.decel := newspeed
		else
			ent^.moveinfo.decel := ent^.moveinfo.decel * ratio;
		ent^.moveinfo.speed := newspeed;
		ent := ent^.teamchain;
	end;
end;

procedure Think_SpawnDoorTrigger (ent:edict_p); cdecl;
var
	other:edict_p;
	mins,maxs:vec3_t;
begin
	if (ent^.flags and FL_TEAMSLAVE<>0) then
		exit;		// only the team leader spawns a trigger

	VectorCopy (ent^.absmin, mins);
	VectorCopy (ent^.absmax, maxs);

  other := ent^.teamchain;
	while Assigned(other) do
	begin
		AddPointToBounds (other^.absmin, mins, maxs);
		AddPointToBounds (other^.absmax, mins, maxs);
		other:=other^.teamchain;
	end;

	// expand
	mins[0] := mins[0] - 60;
	mins[1] := mins[1] - 60;
	maxs[0] := maxs[0] + 60;
	maxs[1] := maxs[1] + 60;

	other := G_Spawn;
	VectorCopy (mins, other^.mins);
	VectorCopy (maxs, other^.maxs);
	other^.owner := ent;
	other^.solid := SOLID_TRIGGER;
	other^.movetype := MOVETYPE_NONE;
	other^.touch := Touch_DoorTrigger;
	gi.linkentity (other);

	if (ent^.spawnflags and DOOR_START_OPEN) <> 0 then
		door_use_areaportals (ent, true);

	Think_CalcMoveSpeed (ent);
end;

procedure door_blocked  (self:edict_p; other:edict_p); cdecl;
var
	ent:edict_p;
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;

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

	if (self^.spawnflags and DOOR_CRUSHER<>0) then
		exit;


// if a door has a negative wait, it would never come back if blocked,
// so let it just squash the object to death real fast
	if (self^.moveinfo.wait >= 0) then
	begin
		if (self^.moveinfo.state = STATE_DOWN) then
		begin
      ent := self^.teammaster;
			while Assigned(ent) do
			begin
				door_go_up (ent, ent^.activator);
				ent := ent^.teamchain;
			end;
		end
		else
		begin
      ent := self^.teammaster;
			while Assigned(ent) do
			begin
				door_go_down (ent);
				ent := ent^.teamchain;
			end;
		end;
	end;
end;

procedure door_killed (self:edict_p; inflictor:edict_p ; attacker:edict_p ; damage:Integer; const point:vec3_t ); cdecl;
var
	ent:edict_p;
begin
  ent := self^.teammaster;
	while Assigned(ent) do
	begin

		ent^.health := ent^.max_health;
		ent^.takedamage := DAMAGE_NO;
		ent:=ent^.teamchain;
	end;
	door_use (self^.teammaster, attacker, attacker);
end;

procedure door_touch (self:edict_p; other:edict_p; plane:cplane_p; surf:csurface_p); cdecl;
begin
	if not Assigned(other^.client) then
		exit;

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

	gi.centerprintf (other, '%s', self^._message);
	gi.sound (other, CHAN_AUTO, gi.soundindex ('misc/talk1.wav'), 1, ATTN_NORM, 0);
end;

procedure SP_func_door (ent:edict_p);
var
	abs_movedir:vec3_t;
begin
	if (ent^.sounds <> 1) then
	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');
	end;

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

	ent^.blocked := door_blocked;
	ent^.use := door_use;

	if (ent^.speed = 0) then
		ent^.speed := 100;
	if (deathmatch^.Value <> 0) then
		ent^.speed := ent^.speed  * 2;

	if (ent^.accel = 0) then
		ent^.accel := ent^.speed;
	if (ent^.decel = 0) then
		ent^.decel := ent^.speed;

	if (ent^.wait = 0) then
		ent^.wait := 3;
	if (st.lip = 0) then
		st.lip := 8;
	if (ent^.dmg = 0) then
		ent^.dmg := 2;

	// calculate second position
	VectorCopy (ent^.s.origin, ent^.pos1);
	abs_movedir[0] := fabs(ent^.movedir[0]);
	abs_movedir[1] := fabs(ent^.movedir[1]);
	abs_movedir[2] := fabs(ent^.movedir[2]);
	ent^.moveinfo.distance := abs_movedir[0] * ent^.size[0] + abs_movedir[1] * ent^.size[1] + abs_movedir[2] * ent^.size[2] - st.lip;
	VectorMA (ent^.pos1, ent^.moveinfo.distance, ent^.movedir, ent^.pos2);

	// if it starts open, switch the positions
	if (ent^.spawnflags and DOOR_START_OPEN) <> 0 then
	begin
		VectorCopy (ent^.pos2, ent^.s.origin);
		VectorCopy (ent^.pos1, ent^.pos2);
		VectorCopy (ent^.s.origin, ent^.pos1);
	end;

	ent^.moveinfo.state := STATE_BOTTOM;

	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^.moveinfo.speed := ent^.speed;
	ent^.moveinfo.accel := ent^.accel;
	ent^.moveinfo.decel := ent^.decel;
	ent^.moveinfo.wait := ent^.wait;
	VectorCopy (ent^.pos1, ent^.moveinfo.start_origin);
	VectorCopy (ent^.s.angles, ent^.moveinfo.start_angles);
	VectorCopy (ent^.pos2, ent^.moveinfo.end_origin);
	VectorCopy (ent^.s.angles, ent^.moveinfo.end_angles);

	if (ent^.spawnflags and 16) <> 0 then
		ent^.s.effects := ent^.s.effects or EF_ANIM_ALL;
	if (ent^.spawnflags and 64) <> 0 then
		ent^.s.effects := ent^.s.effects or EF_ANIM_ALLFAST;

	// to simplify logic elsewhere, make non-teamed doors into a team of one
	if not assigned(ent^.team) then
		ent^.teammaster := ent;

	gi.linkentity (ent);

	ent^.nextthink := level.time + FRAMETIME;
	if (ent^.health <> 0) or assigned(ent^.targetname) then
		ent^.think := Think_CalcMoveSpeed
	else
		ent^.think := Think_SpawnDoorTrigger;
end;


(*QUAKED func_door_rotating (0 .5 .8) ? START_OPEN REVERSE CRUSHER NOMONSTER ANIMATED TOGGLE X_AXIS Y_AXIS
TOGGLE causes the door to wait in both the start and end states for a trigger event.

START_OPEN	the door to moves to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
NOMONSTER	monsters will not trigger this door

You need to have an origin brush as part of this entity.  The center of that brush will be
the point around which it is rotated. It will rotate around the Z axis by default.  You can
check either the X_AXIS or Y_AXIS box to change that.

"distance" is how many degrees the door will be rotated.
"speed" determines how fast the door moves; default value is 100.

REVERSE will cause the door to rotate in the opposite direction.

"message"	is printed when the door is touched if it is a trigger door and it hasn't been fired yet
"angle"		determines the opening direction
"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
"health"	if set, door must be shot open
"speed"		movement speed (100 default)
"wait"		wait before exiting (3 default, -1 := never exit)
"dmg"		damage to inflict when blocked (2 default)
"sounds"
1)	silent
2)	light
3)	medium
4)	heavy
*)

procedure SP_func_door_rotating (ent:edict_p);
begin
	VectorClear (ent^.s.angles);

	// set the axis of rotation
	VectorClear(ent^.movedir);
	if (ent^.spawnflags and DOOR_X_AXIS) <> 0 then
		ent^.movedir[2] := 1.0
	else if (ent^.spawnflags and DOOR_Y_AXIS) <> 0 then
		ent^.movedir[0] := 1.0
	else // Z_AXIS
		ent^.movedir[1] := 1.0;

	// check for reverse rotation
	if (ent^.spawnflags and DOOR_REVERSE) <> 0 then
		VectorNegate (ent^.movedir, ent^.movedir);

	if st.distance = 0 then
	begin
		gi.dprintf('%s at %s with no distance set'#10, ent^.classname, vtos(ent^.s.origin));
		st.distance := 90;
	end;

	VectorCopy (ent^.s.angles, ent^.pos1);
	VectorMA (ent^.s.angles, st.distance, ent^.movedir, ent^.pos2);
	ent^.moveinfo.distance := st.distance;

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

	ent^.blocked := door_blocked;
	ent^.use := door_use;

	if (ent^.speed = 0) then
		ent^.speed := 100;
	if (ent^.accel = 0) then
		ent^.accel := ent^.speed;
	if (ent^.decel = 0) then
		ent^.decel := ent^.speed;

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

	if (ent^.sounds <> 1) then
	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');
	end;

	// if it starts open, switch the positions
	if (ent^.spawnflags and DOOR_START_OPEN) <> 0 then
	begin
		VectorCopy (ent^.pos2, ent^.s.angles);
		VectorCopy (ent^.pos1, ent^.pos2);
		VectorCopy (ent^.s.angles, ent^.pos1);
		VectorNegate (ent^.movedir, ent^.movedir);
	end;

	if (ent^.health) <> 0 then
	begin
		ent^.takedamage := DAMAGE_YES;
		ent^.die := door_killed;
		ent^.max_health := ent^.health;
	end;

	if assigned(ent^.targetname) and assigned(ent^._message) then
	begin
		gi.soundindex ('misc/talk.wav');
		ent^.touch := door_touch;
	end;

	ent^.moveinfo.state := STATE_BOTTOM;
	ent^.moveinfo.speed := ent^.speed;
	ent^.moveinfo.accel := ent^.accel;
	ent^.moveinfo.decel := ent^.decel;
	ent^.moveinfo.wait := ent^.wait;
	VectorCopy (ent^.s.origin, ent^.moveinfo.start_origin);
	VectorCopy (ent^.pos1, ent^.moveinfo.start_angles);
	VectorCopy (ent^.s.origin, ent^.moveinfo.end_origin);
	VectorCopy (ent^.pos2, ent^.moveinfo.end_angles);

	if (ent^.spawnflags and 16) <> 0 then
		ent^.s.effects := ent^.s.effects or EF_ANIM_ALL;

	// to simplify logic elsewhere, make non-teamed doors into a team of one
	if not Assigned(ent^.team) then
		ent^.teammaster := ent;

	gi.linkentity (ent);

	ent^.nextthink := level.time + FRAMETIME;
	if (ent^.health <> 0) or Assigned(ent^.targetname) then
		ent^.think := Think_CalcMoveSpeed
	else
		ent^.think := Think_SpawnDoorTrigger;
end;


(*QUAKED func_water (0 .5 .8) ? START_OPEN
func_water is a moveable water brush.  It must be targeted to operate.  Use a non-water texture at your own risk.

START_OPEN causes the water to move to its destination when spawned and operate in reverse.

"angle"		determines the opening direction (up or down only)
"speed"		movement speed (25 default)
"wait"		wait before exiting (-1 default, -1 := TOGGLE)
"lip"		lip remaining at end of move (0 default)
"sounds"	(yes, these need to be changed)
0)	no sound
1)	water
2)	lava
*)

procedure SP_func_water (self:edict_p);
var
	abs_movedir:vec3_t;
begin
	G_SetMovedir (self^.s.angles, self^.movedir);
	self^.movetype := MOVETYPE_PUSH;
	self^.solid := SOLID_BSP;
	gi.setmodel (self, self^.model);

	case (self^.sounds) of
	 
		 1: // water
		 begin	
			self^.moveinfo.sound_start := gi.soundindex  ('world/mov_watr.wav');
			self^.moveinfo.sound_end := gi.soundindex  ('world/stp_watr.wav');
//			break;
                 end;
		 2: // lava
		 begin
			self^.moveinfo.sound_start := gi.soundindex  ('world/mov_watr.wav');
			self^.moveinfo.sound_end := gi.soundindex  ('world/stp_watr.wav');
//			break;
		 end;
//                 else break;
	end;

	// calculate second position
	VectorCopy (self^.s.origin, self^.pos1);
	abs_movedir[0] := abs(self^.movedir[0]);
	abs_movedir[1] := abs(self^.movedir[1]);
	abs_movedir[2] := abs(self^.movedir[2]);
	self^.moveinfo.distance := abs_movedir[0] * self^.size[0] + abs_movedir[1] * self^.size[1] + abs_movedir[2] * self^.size[2] - st.lip;
	VectorMA (self^.pos1, self^.moveinfo.distance, self^.movedir, self^.pos2);

	// if it starts open, switch the positions
	if (self^.spawnflags and DOOR_START_OPEN) <> 0 then
	begin
		VectorCopy (self^.pos2, self^.s.origin);
		VectorCopy (self^.pos1, self^.pos2);
		VectorCopy (self^.s.origin, self^.pos1);
	end;

	VectorCopy (self^.pos1, self^.moveinfo.start_origin);
	VectorCopy (self^.s.angles, self^.moveinfo.start_angles);
	VectorCopy (self^.pos2, self^.moveinfo.end_origin);
	VectorCopy (self^.s.angles, self^.moveinfo.end_angles);

	self^.moveinfo.state := STATE_BOTTOM;

	if (self^.speed = 0) then
		self^.speed := 25;
	self^.moveinfo.speed := self^.speed;
	self^.moveinfo.decel := self^.moveinfo.speed;
	self^.moveinfo.accel := self^.moveinfo.decel;

	if (self^.wait = 0) then
		self^.wait := -1;
	self^.moveinfo.wait := self^.wait;

	self^.use := door_use;

	if (self^.wait = -1) then
		self^.spawnflags := self^.spawnflags or DOOR_TOGGLE;

	self^.classname := 'func_door';

	gi.linkentity (self);
end;


const
  TRAIN_START_ON	   = 1;
  TRAIN_TOGGLE	     = 2;
  TRAIN_BLOCK_STOPS	 = 4;

(*QUAKED func_train (0 .5 .8) ? START_ON TOGGLE BLOCK_STOPS
Trains are moving platforms that players can ride.
The targets origin specifies the min point of the train at each corner.
The train spawns at the first target it is pointing at.
If the train is the target of a button or trigger, it will not begin moving until activated.
speed	default 100
dmg		default	2
noise	looping sound to play when the train is in motion

*)


procedure train_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;

	if (self^.dmg=0) 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 train_wait (self:edict_p); cdecl;
var
		savetarget:pchar;
		ent:edict_p;
begin
	if assigned(self^.target_ent^.pathtarget) then
	begin


		ent := self^.target_ent;
		savetarget := ent^.target;
		ent^.target := ent^.pathtarget;
		G_UseTargets (ent, self^.activator);
		ent^.target := savetarget;

		// make sure we didn't get killed by a killtarget
		if (not self^.inuse) then
			exit;
	end;

	if (self^.moveinfo.wait<>0) then
	begin
		if (self^.moveinfo.wait > 0) then
		begin
			self^.nextthink := level.time + self^.moveinfo.wait;
			self^.think := train_next;
		end
		else if (self^.spawnflags and TRAIN_TOGGLE) <> 0 then  // && wait < 0
		begin
			train_next (self);
			self^.spawnflags := self^.spawnflags and not TRAIN_START_ON;
			VectorClear (self^.velocity);

⌨️ 快捷键说明

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