Пример #1
0
void target_lock_use (edict_t *self, edict_t *other, edict_t *activator)
{
	edict_t *e;
	int		n;
	char    current[16];
	char	*copy_message;

	memset(current,0,16);

	for (e = self->teammaster; e; e = e->teamchain)
	{
		if (!e->count)
			continue;
		n = e->count - 1;
		current[n] = '0' + e->s.frame;
	}
	if(strcmp(current,self->key_message)==0)
	{
		copy_message  = self->message;
		self->message = NULL;
		G_UseTargets(self,activator);
		self->message = copy_message;
	}
	else
	{
		if(self->message) safe_centerprintf(activator,self->message);
		if(self->pathtarget) {
			e = G_Find(NULL,FOFS(targetname),self->pathtarget);
			if(e) e->use(e,other,activator);
		}
		else {
			BeepBeep(activator);
		}
	}
}
Пример #2
0
void crane_control_action(edict_t *control, edict_t *activator, vec3_t point)
{
	float  Z;
	int    dir;
	int    row, column;
	int    content;
	edict_t *beam, *cable, *cargo, *hoist, *hook;
	trace_t tr;
	vec3_t  center, v;
	vec3_t  end, forward, start, pt;
	vec3_t  bonk, mins, maxs;

	if(!(control->spawnflags & 1))
	{
		if(control->message)
			safe_centerprintf(activator,"%s\n",control->message);
		else
			safe_centerprintf(activator,"No power\n");
		return;
	}

	if(control->busy) return;

	// First make sure player (activator) is on the panel side of the
	// control panel
	// Also get center point of panel side
	switch (control->style)
	{
	case 0:
		if(activator->s.origin[0] > control->absmax[0]) return;
		center[0] = control->absmin[0];
		center[1] = (control->absmin[1] + control->absmax[1])/2;
		center[2] = (control->absmin[2] + control->absmax[2])/2;
		break;
	case 1:
		if(activator->s.origin[1] > control->absmax[1]) return;
		center[0] = (control->absmin[0] + control->absmax[0])/2;
		center[1] = control->absmin[1];
		center[2] = (control->absmin[2] + control->absmax[2])/2;
		break;
	case 2:
		if(activator->s.origin[0] < control->absmin[0]) return;
		center[0] = control->absmax[0];
		center[1] = (control->absmin[1] + control->absmax[1])/2;
		center[2] = (control->absmin[2] + control->absmax[2])/2;
		break;
	case 3:
		if(activator->s.origin[1] < control->absmin[1]) return;
		center[0] = (control->absmin[0] + control->absmax[0])/2;
		center[1] = control->absmax[1];
		center[2] = (control->absmin[2] + control->absmax[2])/2;
		break;
	}
	// now check distance from player to panel
	VectorSubtract(activator->s.origin,center,v);
	if(VectorLength(v) > 64) return;

	beam  = control->crane_beam;
	cable = control->crane_cable;
	hoist = control->crane_hoist;
	hook  = control->crane_hook;
	cargo = hook->crane_cargo;
	if(cargo) cargo->gravity = 0.0;    // reset after making it float up,
									   // otherwise things get jammed up
	control->activator = activator;

	// if any part of crane is currently moving, do nothing.
	if(VectorLength(control->velocity) > 0.) return;
	if(VectorLength(beam->velocity)    > 0.) return;
	if(VectorLength(hoist->velocity)   > 0.) return;
	if(VectorLength(hook->velocity)    > 0.) return;

	// now find which row and column of buttons corresponds to "point"
	row = (2*(point[2] - control->absmin[2]))/(control->absmax[2]-control->absmin[2]);
	if(row < 0) row = 0;
	if(row > 1) row = 1;
	switch (control->style)
	{
	case 1:
		column = (4*(point[0]-control->absmin[0]))/(control->absmax[0]-control->absmin[0]);
		break;
	case 2:
		column = (4*(point[1]-control->absmin[1]))/(control->absmax[1]-control->absmin[1]);
		break;
	case 3:
		column = (4*(point[0]-control->absmax[0]))/(control->absmin[0]-control->absmax[0]);
		break;
	default:
		column = (4*(point[1]-control->absmax[1]))/(control->absmin[1]-control->absmax[1]);
		break;
	}
	if(column < 0) column = 0;
	if(column > 3) column = 3;

	// adjust for controller facing beam movement direction
	if( beam->movedir[0] > 0 && (control->style == 0 || control->style == 2)) {
		if(column == 0 || column == 1) {
			column = 1-column;
			row = 1-row;
		}
	}
	if( beam->movedir[1] > 0 && (control->style == 1 || control->style == 3)) {
		if(column == 0 || column == 1) {
			column = 1-column;
			row = 1-row;
		}
	}

	switch(column)
	{
	case 0:
		//==================
		// move hoist
		//==================
		if(row)
		{
			// hoist away
			if(control->style == 0 || control->style == 1)
				control->crane_increment = 1;
			else
				control->crane_increment = -1;
		}
		else
		{
			// hoist toward
			if(control->style == 0 || control->style == 1)
				control->crane_increment = -1;
			else
				control->crane_increment = 1;
		}
		if(hoist->movedir[0] > 0)
		{
			// hoist travels in X
			dir = 0;
			if(control->crane_increment > 0)
			{
				if(Crane_Hook_Bonk(hook,0,1,bonk))
				{
					bonk[0] += hoist->absmax[0] - hook->absmax[0];
					hoist->crane_bonk = min(bonk[0],hoist->pos2[0]);
				}
				else
					hoist->crane_bonk = hoist->pos2[0];
				hoist->crane_bonk += hoist->absmin[0] - hoist->absmax[0];
			}
			else
			{
				if(Crane_Hook_Bonk(hook,0,-1,bonk))
				{
					bonk[0] += hoist->absmin[0] - hook->absmin[0];
					hoist->crane_bonk = max(bonk[0],hoist->pos1[0]);
				}
				else
					hoist->crane_bonk = hoist->pos1[0];
			}
		}
		else
		{
			// travels in Y
			dir = 1;
			if(control->crane_increment > 0)
			{
				if(Crane_Hook_Bonk(hook,1,1,bonk))
				{
					bonk[1] += hoist->absmax[1] - hook->absmax[1];
					hoist->crane_bonk = min(bonk[1],hoist->pos2[1]);
				}
				else
					hoist->crane_bonk = hoist->pos2[1];
				hoist->crane_bonk += hoist->absmin[1] - hoist->absmax[1];

			}
			else
			{
				if(Crane_Hook_Bonk(hook,1,-1,bonk))
				{
					bonk[1] += hoist->absmin[1] - hook->absmin[1];
					hoist->crane_bonk = max(bonk[1],hoist->pos1[1]);
				}
				else
					hoist->crane_bonk = hoist->pos1[1];
			}
		}
		hoist->crane_dir = dir;
		hoist->moveinfo.remaining_distance = control->crane_increment *
			(hoist->crane_bonk - hoist->absmin[dir]);
		if(hoist->moveinfo.remaining_distance <= 0) return;

		hoist->moveinfo.remaining_distance = min(hoist->moveinfo.remaining_distance,STEPSIZE);
		Crane_AdjustSpeed(hoist);
		VectorSet(hoist->moveinfo.dir,
			hoist->movedir[0]*control->crane_increment,
			hoist->movedir[1]*control->crane_increment,
			0);
		hoist->crane_control = control;

		hook->crane_dir  = dir;
		hook->crane_bonk = hoist->crane_bonk + hook->absmin[dir] -
			hoist->absmin[dir];
		hook->crane_control = control;
		memcpy(&hook->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t));

		cable->crane_dir  = dir;
		cable->crane_bonk = hoist->crane_bonk + cable->absmin[dir] -
			hoist->absmin[dir];
		cable->crane_control = control;
		memcpy(&cable->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t));

		if(cargo)
		{
			cargo->movetype   = MOVETYPE_PUSH;
			cargo->crane_dir  = dir;
			cargo->crane_bonk = hoist->crane_bonk + cargo->absmin[dir] -
				hoist->absmin[dir];
			cargo->crane_control = control;
			memcpy(&cargo->moveinfo,&hoist->moveinfo,sizeof(moveinfo_t));
		}
		Crane_Move_Begin(hoist);
		Crane_Move_Begin(hook);
		if(cargo) Crane_Move_Begin(cargo);
		break;
	case 1:
		//==================
		// move beam
		//==================
		// first re-parent associated speaker, if any
		if(beam->speaker && control == beam->crane_onboard_control)
		{
			beam->speaker->owner = control;
			VectorAdd(control->absmin,control->absmax,beam->speaker->s.origin);
			VectorScale(beam->speaker->s.origin,0.5,beam->speaker->s.origin);
			VectorSubtract(beam->speaker->s.origin,control->s.origin,beam->speaker->offset);
			control->noise_index = beam->noise_index;
		}
		if(row)
		{
			// left arrow
			if(control->style == 0 || control->style == 3)
				control->crane_increment =  1;
			else
				control->crane_increment = -1;
		}
		else
		{
			// right arrow
			if(control->style == 0 || control->style == 3)
				control->crane_increment = -1;
			else
				control->crane_increment =  1;
		}
		if(beam->movedir[0] > 0)
		{
			// travels in X
			dir = 0;
			if(control->crane_increment > 0)
			{
				if(Crane_Hook_Bonk(hook,0,1,bonk))
				{
					bonk[0] += beam->absmax[0] - hook->absmax[0];
					beam->crane_bonk = min(bonk[0],beam->pos2[0]);
				}
				else
					beam->crane_bonk = beam->pos2[0];
				beam->crane_bonk += beam->absmin[0] - beam->absmax[0];
			}
			else
			{
				if(Crane_Hook_Bonk(hook,0,-1,bonk))
				{
					bonk[0] += beam->absmin[0] - hook->absmin[0];
					beam->crane_bonk = max(bonk[0],beam->pos1[0]);
				}
				else
					beam->crane_bonk = beam->pos1[0];
			}
		}
		else
		{
			// travels in Y
			dir = 1;
			if(control->crane_increment > 0)
			{
				if(Crane_Hook_Bonk(hook,1,1,bonk))
				{
					bonk[1] += beam->absmax[1] - hook->absmax[1];
					beam->crane_bonk = min(bonk[1],beam->pos2[1]);
				}
				else
					beam->crane_bonk = beam->pos2[1];
				beam->crane_bonk += beam->absmin[1] - beam->absmax[1];
			}
			else
			{
				if(Crane_Hook_Bonk(hook,1,-1,bonk))
				{
					bonk[1] += beam->absmin[1] - hook->absmin[1];
					beam->crane_bonk = max(bonk[1],beam->pos1[1]);
				}
				else
					beam->crane_bonk = beam->pos1[1];
			}
		}
		beam->crane_dir = dir;
		beam->moveinfo.remaining_distance = control->crane_increment *
			(beam->crane_bonk - beam->absmin[dir]);
//		gi.dprintf("remaining distance = %g\n",beam->moveinfo.remaining_distance);
		if(beam->moveinfo.remaining_distance <= 0) return;
		beam->moveinfo.remaining_distance = min(beam->moveinfo.remaining_distance,STEPSIZE);

		Crane_AdjustSpeed(beam);

		VectorSet(beam->moveinfo.dir,
			beam->movedir[0]*control->crane_increment,
			beam->movedir[1]*control->crane_increment,
			0);
		beam->crane_control = control;

		hoist->crane_dir  = dir;
		hoist->crane_bonk = beam->crane_bonk + hoist->absmin[dir] - beam->absmin[dir];
		hoist->crane_control = control;
		memcpy(&hoist->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));

		hook->crane_dir   = dir;
		hook->crane_bonk  = beam->crane_bonk + hook->absmin[dir] - beam->absmin[dir];
		hook->crane_control = control;
		memcpy(&hook->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));

		cable->crane_dir  = dir;
		cable->crane_bonk = beam->crane_bonk + cable->absmin[dir] -
			beam->absmin[dir];
		cable->crane_control = control;
		memcpy(&cable->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
		
		if(beam->crane_onboard_control)
		{
			beam->crane_onboard_control->crane_dir  = dir;
			beam->crane_onboard_control->crane_bonk = beam->crane_bonk +
				beam->crane_onboard_control->absmin[dir] -
				beam->absmin[dir];
			beam->crane_onboard_control->crane_control = control;
			memcpy(&beam->crane_onboard_control->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
		}

		if(cargo)
		{
			cargo->movetype   = MOVETYPE_PUSH;
			cargo->crane_dir  = dir;
			cargo->crane_bonk = beam->crane_bonk + cargo->absmin[dir] - beam->absmin[dir];
			cargo->crane_control = control;
			memcpy(&cargo->moveinfo,&beam->moveinfo,sizeof(moveinfo_t));
		}
		Crane_Move_Begin(beam);
		Crane_Move_Begin(hoist);
		Crane_Move_Begin(hook);
		if(beam->crane_onboard_control)
			Crane_Move_Begin(beam->crane_onboard_control);
		if(cargo) Crane_Move_Begin(cargo);
		break;
	case 2:
		//==================
		// hook up/down
		//==================
		hook->crane_dir = dir = 2;
		if(row)
		{
			// hook up
			control->crane_increment = 1;
			if(Crane_Hook_Bonk(hook,2,1,bonk))
				hook->crane_bonk = min(bonk[2],hook->pos2[2]);
			else
				hook->crane_bonk = hook->pos2[2];
			hook->crane_bonk += hook->absmin[2] - hook->absmax[2];
		}
		else
		{
			// hook down
			if(cargo)
			{
				pt[0] = (cargo->absmin[0] + cargo->absmax[0])/2;
				pt[1] = (cargo->absmin[1] + cargo->absmax[1])/2;
				pt[2] = cargo->absmin[2] - 0.125;
				content = gi.pointcontents(pt);
				if(content & MASK_SOLID)
				{
					BeepBeep(activator);
					return;
				}
			}
			control->crane_increment = -1;
			if(Crane_Hook_Bonk(hook,2,-1,bonk))
				hook->crane_bonk = max(bonk[2],hook->pos1[2]);
			else
				hook->crane_bonk = hook->pos1[2];
		}
		hook->moveinfo.remaining_distance = control->crane_increment *
			(hook->crane_bonk - hook->absmin[hook->crane_dir]);
		if(hook->moveinfo.remaining_distance <= 0)
		{
			BeepBeep(activator);
			return;
		}
		hook->moveinfo.remaining_distance = min(hook->moveinfo.remaining_distance,STEPSIZE);
		Crane_AdjustSpeed(hook);
		VectorSet(hook->moveinfo.dir,0.,0.,(float)(control->crane_increment));
		hook->crane_control = control;
		if(cargo)
		{
			cargo->movetype   = MOVETYPE_PUSH;
			cargo->crane_dir  = dir;
			cargo->crane_bonk = hook->crane_bonk + cargo->absmin[dir] - hook->absmin[dir];
			cargo->crane_control = control;
			VectorSubtract(cargo->s.origin,hook->s.origin,cargo->offset);
			memcpy(&cargo->moveinfo,&hook->moveinfo,sizeof(moveinfo_t));
		}
		cable->think = Cable_Think;
		cable->nextthink = level.time + FRAMETIME;

		Crane_Move_Begin(hook);
		if(cargo) Crane_Move_Begin(cargo);
		break;
	case 3:
		//==================
		// hook/unhook
		//==================
		if(row)
		{
			// pickup cargo

			if(hook->crane_cargo)
			{
				// already carrying something
				BeepBeep(activator);
				return;
			}
			VectorAdd(hook->absmin,hook->absmax,start);
			VectorScale(start,0.5,start);
			VectorSet(forward,0.,0.,-1.);
			VectorMA(start, 8192, forward, end);
			VectorSubtract(hook->absmin,start,mins);
			VectorSubtract(hook->absmax,start,maxs);
			// 06/03/00 change: Use 1/3 the bounding box to force a better hit
			VectorScale(mins,0.3333,mins);
			VectorScale(maxs,0.3333,maxs);
			// end 06/03/00 change
			tr=gi.trace(start, mins, maxs, end, hook, MASK_SOLID);
			if((tr.fraction < 1) && (tr.ent) && (tr.ent->classname) &&
				(tr.ent->movetype == MOVETYPE_PUSHABLE) )
			{
				Z = hook->absmin[2] - tr.ent->absmax[2];
				if(Z > MAX_PICKUP_DISTANCE)
				{
					safe_centerprintf(activator,"Too far\n");
					return;
				}
				if(CrateOnTop(NULL,tr.ent))
				{
					BeepBeep(activator);
					gi.dprintf("Too heavy\n");
					return;
				}
				// run a trace from top of cargo up... if first entity hit is NOT
				// the hook, we can't get there from here.
				if( Z > 0 )
				{
					trace_t tr2;

					VectorMA(tr.ent->mins,0.5,tr.ent->size,start);
					start[2] = tr.ent->maxs[2];
					VectorCopy(tr.ent->size,mins);
					VectorScale(mins,-0.5,mins);
					VectorCopy(tr.ent->size,maxs);
					VectorScale(maxs,0.5,maxs);
					mins[2] = maxs[2] = 0;
					mins[0] += 1; mins[1] += 1; maxs[0] -= 1; maxs[1] -= 1;
					VectorCopy(start,end);
					end[2] += Z + 1;
					tr2=gi.trace(start, mins, maxs, end, hook, MASK_SOLID);
					if((tr2.fraction < 1) && tr2.ent && (tr2.ent != hook))
					{
						safe_centerprintf(activator,"Blocked!\n");
						return;
					}
				}
				Z -= CARGO_BUFFER;   // leave a buffer between hook and cargo
				hook->crane_cargo    = cargo = tr.ent;
				cargo->groundentity  = NULL;
				cargo->crane_control = control;
				cargo->crane_hook    = hook;
				cargo->movetype      = MOVETYPE_PUSH;
				cargo->touch         = NULL;
				// Make cargo float up to the hook
				if(Z > 0)
				{
					control->busy      = true;
					cargo->attracted   = true;
					cargo->gravity     = 0.0;
					cargo->velocity[2] = 0.0;
					cargo->think       = Cargo_Float_Up;
					cargo->blocked     = cargo_blocked;
					cargo->goal_frame  = level.framenum;
					cargo->nextthink   = level.time + FRAMETIME;
					gi.linkentity(cargo);
				}
				else
				{
					gi.positioned_sound (start, cargo, CHAN_VOICE,
						gi.soundindex("tank/thud.wav"), 1, 1, 0);
				}
			}
			else
				BeepBeep(activator);
		}
		else
		{
			// drop cargo

			if(hook->crane_cargo)
			{
				hook->crane_cargo->gravity    = 1.0;
				hook->crane_cargo->movetype   = MOVETYPE_PUSHABLE;
				hook->crane_cargo->touch      = box_touch;
				hook->crane_cargo->crane_control = NULL;
				gi.linkentity(hook->crane_cargo);
				box_movestep (hook->crane_cargo, vec3_origin, true);
				hook->crane_cargo = NULL;
			}
			else
				BeepBeep(activator);
		}
	}
}