// ------------------------------------------------------------------------------- //when the wall has used all its hitpoints, this will destroy it void blast_blastable_wall(segment *seg, int side) { int Connectside; segment *csegp; int a, n; Assert(seg->sides[side].wall_num != -1); Walls[seg->sides[side].wall_num].hps = -1; //say it's blasted csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); kill_stuck_objects(seg->sides[side].wall_num); kill_stuck_objects(csegp->sides[Connectside].wall_num); //if this is an exploding wall, explode it if (WallAnims[Walls[seg->sides[side].wall_num].clip_num].flags & WCF_EXPLODES) explode_wall(seg-Segments,side); else { //if not exploding, set final frame, and make door passable a = Walls[seg->sides[side].wall_num].clip_num; n = WallAnims[a].num_frames; wall_set_tmap_num(seg,side,csegp,Connectside,a,n-1); Walls[seg->sides[side].wall_num].flags |= WALL_BLASTED; Walls[csegp->sides[Connectside].wall_num].flags |= WALL_BLASTED; } }
// ------------------------------------------------------------------------------- //when the wall has used all its hitpoints, this will destroy it void blast_blastable_wall(segment *seg, int side) { int Connectside; segment *csegp; int a, n; Assert(seg->sides[side].wall_num != -1); csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); kill_stuck_objects(seg->sides[side].wall_num); kill_stuck_objects(csegp->sides[Connectside].wall_num); a = Walls[seg->sides[side].wall_num].clip_num; n = WallAnims[a].num_frames; if (!(WallAnims[Walls[seg->sides[side].wall_num].clip_num].flags & WCF_EXPLODES)) wall_set_tmap_num(seg,side,csegp,Connectside,a,n-1); Walls[seg->sides[side].wall_num].flags |= WALL_BLASTED; Walls[csegp->sides[Connectside].wall_num].flags |= WALL_BLASTED; //if this is an exploding wall, explode it if (WallAnims[Walls[seg->sides[side].wall_num].clip_num].flags & WCF_EXPLODES) explode_wall(seg-Segments,side); }
//----------------------------------------------------------------- // Deteriorate appearance of wall. (Changes bitmap (paste-ons)) void wall_damage(segment *seg, int side, fix damage) { int a, i, n; if (seg->sides[side].wall_num == -1) { mprintf((0, "Damaging illegal wall\n")); return; } if (Walls[seg->sides[side].wall_num].type != WALL_BLASTABLE) return; if (!(Walls[seg->sides[side].wall_num].flags & WALL_BLASTED) && Walls[seg->sides[side].wall_num].hps >= 0) { int Connectside; segment *csegp; csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); Walls[seg->sides[side].wall_num].hps -= damage; Walls[csegp->sides[Connectside].wall_num].hps -= damage; a = Walls[seg->sides[side].wall_num].clip_num; n = WallAnims[a].num_frames; if (Walls[seg->sides[side].wall_num].hps < WALL_HPS*1/n) { blast_blastable_wall( seg, side ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_door_open(seg-Segments, side,Walls[seg->sides[side].wall_num].flags); #endif } else for (i=0;i<n;i++) if (Walls[seg->sides[side].wall_num].hps < WALL_HPS*(n-i)/n) { wall_set_tmap_num(seg,side,csegp,Connectside,a,i); } } }
//----------------------------------------------------------------- // This function closes the specified door and restores the closed // door texture. This is called when the animation is done void wall_close_door_num(int door_num) { int p; active_door *d; int i, cwall_num; d = &ActiveDoors[door_num]; for (p=0;p<d->n_parts;p++) { wall *w; int Connectside, side; segment *csegp, *seg; w = &Walls[d->front_wallnum[p]]; seg = &Segments[w->segnum]; side = w->sidenum; Assert(seg->sides[side].wall_num != -1); //Closing door on illegal wall csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); cwall_num = csegp->sides[Connectside].wall_num; Walls[seg->sides[side].wall_num].state = WALL_DOOR_CLOSED; if (cwall_num > -1) Walls[cwall_num].state = WALL_DOOR_CLOSED; wall_set_tmap_num(seg,side,csegp,Connectside,w->clip_num,0); } for (i=door_num;i<Num_open_doors;i++) ActiveDoors[i] = ActiveDoors[i+1]; Num_open_doors--; }
//----------------------------------------------------------------- // Animates and processes the closing of a door. // Called from the game loop. void do_door_close(int door_num) { int p; active_door *d; wall *w; Assert(door_num != -1); //Trying to do_door_open on illegal door d = &ActiveDoors[door_num]; w = &Walls[d->front_wallnum[0]]; //check for objects in doorway before closing if (w->flags & WALL_DOOR_AUTO) if (!is_door_free(&Segments[w->segnum],w->sidenum)) { digi_kill_sound_linked_to_segment(w->segnum,w->sidenum,-1); wall_open_door(&Segments[w->segnum],w->sidenum); //re-open door return; } for (p=0;p<d->n_parts;p++) { wall *w; int Connectside, side; segment *csegp, *seg; fix time_elapsed, time_total, one_frame; int i, n; w = &Walls[d->front_wallnum[p]]; seg = &Segments[w->segnum]; side = w->sidenum; if (seg->sides[side].wall_num == -1) { mprintf((0, "Trying to do_door_close on Illegal wall\n")); return; } //if here, must be auto door // Assert(Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO); //don't assert here, because now we have triggers to close non-auto doors // Otherwise, close it. csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); if ( Newdemo_state != ND_STATE_PLAYBACK ) // NOTE THE LINK TO ABOVE!! if (p==0) //only play one sound for linked doors if ( d->time==0 ) { //first time vms_vector cp; compute_center_point_on_side(&cp, seg, side ); if (WallAnims[w->clip_num].close_sound > -1 ) digi_link_sound_to_pos( WallAnims[Walls[seg->sides[side].wall_num].clip_num].close_sound, seg-Segments, side, &cp, 0, F1_0 ); } d->time += FrameTime; time_elapsed = d->time; n = WallAnims[w->clip_num].num_frames; time_total = WallAnims[w->clip_num].play_time; one_frame = time_total/n; i = n-time_elapsed/one_frame-1; if (i < n/2) { Walls[seg->sides[side].wall_num].flags &= ~WALL_DOOR_OPENED; Walls[csegp->sides[Connectside].wall_num].flags &= ~WALL_DOOR_OPENED; } // Animate door. if (i > 0) { wall_set_tmap_num(seg,side,csegp,Connectside,w->clip_num,i); Walls[seg->sides[side].wall_num].state = WALL_DOOR_CLOSING; Walls[csegp->sides[Connectside].wall_num].state = WALL_DOOR_CLOSING; ActiveDoors[Num_open_doors].time = 0; //counts up } else wall_close_door_num(door_num); } }
//----------------------------------------------------------------- // Animates opening of a door. // Called in the game loop. void do_door_open(int door_num) { int p; active_door *d; Assert(door_num != -1); //Trying to do_door_open on illegal door d = &ActiveDoors[door_num]; for (p=0;p<d->n_parts;p++) { wall *w; int Connectside, side; segment *csegp, *seg; fix time_elapsed, time_total, one_frame; int i, n; w = &Walls[d->front_wallnum[p]]; kill_stuck_objects(d->front_wallnum[p]); kill_stuck_objects(d->back_wallnum[p]); seg = &Segments[w->segnum]; side = w->sidenum; Assert(seg->sides[side].wall_num != -1); //Trying to do_door_open on illegal wall csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); d->time += FrameTime; time_elapsed = d->time; n = WallAnims[w->clip_num].num_frames; time_total = WallAnims[w->clip_num].play_time; one_frame = time_total/n; i = time_elapsed/one_frame; if (i < n) wall_set_tmap_num(seg,side,csegp,Connectside,w->clip_num,i); if (i> n/2) { Walls[seg->sides[side].wall_num].flags |= WALL_DOOR_OPENED; Walls[csegp->sides[Connectside].wall_num].flags |= WALL_DOOR_OPENED; } if (i >= n-1) { wall_set_tmap_num(seg,side,csegp,Connectside,w->clip_num,n-1); // If our door is not automatic just remove it from the list. if (!(Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO)) { for (i=door_num;i<Num_open_doors;i++) ActiveDoors[i] = ActiveDoors[i+1]; Num_open_doors--; Walls[seg->sides[side].wall_num].state = WALL_DOOR_OPEN; Walls[csegp->sides[Connectside].wall_num].state = WALL_DOOR_OPEN; } else { Walls[seg->sides[side].wall_num].state = WALL_DOOR_WAITING; Walls[csegp->sides[Connectside].wall_num].state = WALL_DOOR_WAITING; ActiveDoors[Num_open_doors].time = 0; //counts up } } } }
//----------------------------------------------------------------- // Animates and processes the closing of a door. // Called from the game loop. void do_door_close(int door_num) { int p; active_door *d; wall *w; Assert(door_num != -1); //Trying to do_door_open on illegal door d = &ActiveDoors[door_num]; w = &Walls[d->front_wallnum[0]]; //check for objects in doorway before closing if (w->flags & WALL_DOOR_AUTO) for (p=0;p<d->n_parts;p++) { int Connectside, side; segment *csegp, *seg; int objnum; seg = &Segments[w->segnum]; side = w->sidenum; csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); //go through each object in each of two segments, and see if //it pokes into the connecting seg for (objnum=seg->objects;objnum!=-1;objnum=Objects[objnum].next) if (check_poke(objnum,seg-Segments,side)) return; //abort! for (objnum=csegp->objects;objnum!=-1;objnum=Objects[objnum].next) if (check_poke(objnum,csegp-Segments,Connectside)) return; //abort! } for (p=0;p<d->n_parts;p++) { wall *w; int Connectside, side; segment *csegp, *seg; fix time_elapsed, time_total, one_frame; int i, n; w = &Walls[d->front_wallnum[p]]; seg = &Segments[w->segnum]; side = w->sidenum; if (seg->sides[side].wall_num == -1) { return; } //if here, must be auto door Assert(Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO); // Otherwise, close it. csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); Assert(Connectside != -1); if ( Newdemo_state != ND_STATE_PLAYBACK ) // NOTE THE LINK TO ABOVE!! if (p==0) //only play one sound for linked doors if ( d->time==0 ) { //first time vms_vector cp; compute_center_point_on_side(&cp, seg, side ); if (WallAnims[w->clip_num].close_sound > -1 ) digi_link_sound_to_pos( WallAnims[Walls[seg->sides[side].wall_num].clip_num].close_sound, seg-Segments, side, &cp, 0, F1_0 ); } d->time += FrameTime; time_elapsed = d->time; n = WallAnims[w->clip_num].num_frames; time_total = WallAnims[w->clip_num].play_time; one_frame = time_total/n; i = n-time_elapsed/one_frame-1; if (i < n/2) { Walls[seg->sides[side].wall_num].flags &= ~WALL_DOOR_OPENED; Walls[csegp->sides[Connectside].wall_num].flags &= ~WALL_DOOR_OPENED; } // Animate door. if (i > 0) { wall_set_tmap_num(seg,side,csegp,Connectside,w->clip_num,i); Walls[seg->sides[side].wall_num].state = WALL_DOOR_CLOSING; Walls[csegp->sides[Connectside].wall_num].state = WALL_DOOR_CLOSING; ActiveDoors[Num_open_doors].time = 0; //counts up } else wall_close_door(door_num); } }