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); } } }
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); } } }