📄 po_man.c
字号:
for(i = po->bbox[BOXLEFT]; i <= po->bbox[BOXRIGHT]; i++) { if(i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight*bmapwidth) { link = &PolyBlockMap[j+i]; if(!(*link)) { // Create a new link at the current block cell *link = Z_Malloc(sizeof(polyblock_t), PU_LEVEL, 0); (*link)->next = NULL; (*link)->prev = NULL; (*link)->polyobj = po; continue; } else { tempLink = *link; while(tempLink->next != NULL && tempLink->polyobj != NULL) { tempLink = tempLink->next; } } if(tempLink->polyobj == NULL) { tempLink->polyobj = po; continue; } else { tempLink->next = Z_Malloc(sizeof(polyblock_t), PU_LEVEL, 0); tempLink->next->next = NULL; tempLink->next->prev = tempLink; tempLink->next->polyobj = po; } } // else, don't link the polyobj, since it's off the map } }}//==========================================================================//// CheckMobjBlocking////==========================================================================static boolean CheckMobjBlocking(seg_t *seg, polyobj_t *po){ mobj_t *mobj; int i, j; int left, right, top, bottom; int tmbbox[4]; line_t *ld; boolean blocked; ld = seg->linedef; top = (ld->bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; bottom = (ld->bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; left = (ld->bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; right = (ld->bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; blocked = false; bottom = bottom < 0 ? 0 : bottom; bottom = bottom >= bmapheight ? bmapheight-1 : bottom; top = top < 0 ? 0 : top; top = top >= bmapheight ? bmapheight-1 : top; left = left < 0 ? 0 : left; left = left >= bmapwidth ? bmapwidth-1 : left; right = right < 0 ? 0 : right; right = right >= bmapwidth ? bmapwidth-1 : right; for(j = bottom*bmapwidth; j <= top*bmapwidth; j += bmapwidth) { for(i = left; i <= right; i++) { for(mobj = blocklinks[j+i]; mobj; mobj = mobj->bnext) { if(mobj->flags&MF_SOLID || mobj->player) { tmbbox[BOXTOP] = mobj->y+mobj->radius; tmbbox[BOXBOTTOM] = mobj->y-mobj->radius; tmbbox[BOXLEFT] = mobj->x-mobj->radius; tmbbox[BOXRIGHT] = mobj->x+mobj->radius; if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) { continue; } if(P_BoxOnLineSide(tmbbox, ld) != -1) { continue; } ThrustMobj(mobj, seg, po); blocked = true; } } } } return blocked;}//==========================================================================//// InitBlockMap////==========================================================================static void InitBlockMap(void){ int i; int j; seg_t **segList; int area; int leftX, rightX; int topY, bottomY; PolyBlockMap = Z_Malloc(bmapwidth*bmapheight*sizeof(polyblock_t *), PU_LEVEL, 0); memset(PolyBlockMap, 0, bmapwidth*bmapheight*sizeof(polyblock_t *)); for(i = 0; i < po_NumPolyobjs; i++) { LinkPolyobj(&polyobjs[i]); // calculate a rough area // right now, working like shit...gotta fix this... segList = polyobjs[i].segs; leftX = rightX = (*segList)->v1->x; topY = bottomY = (*segList)->v1->y; for(j = 0; j < polyobjs[i].numsegs; j++, segList++) { if((*segList)->v1->x < leftX) { leftX = (*segList)->v1->x; } if((*segList)->v1->x > rightX) { rightX = (*segList)->v1->x; } if((*segList)->v1->y < bottomY) { bottomY = (*segList)->v1->y; } if((*segList)->v1->y > topY) { topY = (*segList)->v1->y; } } area = ((rightX>>FRACBITS)-(leftX>>FRACBITS))* ((topY>>FRACBITS)-(bottomY>>FRACBITS));// fprintf(stdaux, "Area of Polyobj[%d]: %d\n", polyobjs[i].tag, area);// fprintf(stdaux, "\t[%d]\n[%d]\t\t[%d]\n\t[%d]\n", topY>>FRACBITS, // leftX>>FRACBITS,// rightX>>FRACBITS, bottomY>>FRACBITS); }}//==========================================================================//// IterFindPolySegs//// Passing NULL for segList will cause IterFindPolySegs to// count the number of segs in the polyobj//==========================================================================static void IterFindPolySegs(int x, int y, seg_t **segList){ int i; if(x == PolyStartX && y == PolyStartY) { return; } for(i = 0; i < numsegs; i++) { if(segs[i].v1->x == x && segs[i].v1->y == y) { if(!segList) { PolySegCount++; } else { *segList++ = &segs[i]; } IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, segList); return; } } I_Error("IterFindPolySegs: Non-closed Polyobj located.\n");}//==========================================================================//// SpawnPolyobj////==========================================================================static void SpawnPolyobj(int index, int tag, boolean crush){ int i; int j; int psIndex; int psIndexOld; seg_t *polySegList[PO_MAXPOLYSEGS]; for(i = 0; i < numsegs; i++) { if(segs[i].linedef->special == PO_LINE_START && segs[i].linedef->arg1 == tag) { if(polyobjs[index].segs) { I_Error("SpawnPolyobj: Polyobj %d already spawned.\n", tag); } segs[i].linedef->special = 0; segs[i].linedef->arg1 = 0; PolySegCount = 1; PolyStartX = segs[i].v1->x; PolyStartY = segs[i].v1->y; IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, NULL); polyobjs[index].numsegs = PolySegCount; polyobjs[index].segs = Z_Malloc(PolySegCount*sizeof(seg_t *), PU_LEVEL, 0); *(polyobjs[index].segs) = &segs[i]; // insert the first seg IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, polyobjs[index].segs+1); polyobjs[index].crush = crush; polyobjs[index].tag = tag; polyobjs[index].seqType = segs[i].linedef->arg3; if(polyobjs[index].seqType < 0 || polyobjs[index].seqType >= SEQTYPE_NUMSEQ) { polyobjs[index].seqType = 0; } break; } } if(!polyobjs[index].segs) { // didn't find a polyobj through PO_LINE_START psIndex = 0; polyobjs[index].numsegs = 0; for(j = 1; j < PO_MAXPOLYSEGS; j++) { psIndexOld = psIndex; for (i = 0; i < numsegs; i++) { if(segs[i].linedef->special == PO_LINE_EXPLICIT && segs[i].linedef->arg1 == tag) { if(!segs[i].linedef->arg2) { I_Error("SpawnPolyobj: Explicit line missing order number (probably %d) in poly %d.\n", j+1, tag); } if(segs[i].linedef->arg2 == j) { polySegList[psIndex] = &segs[i]; polyobjs[index].numsegs++; psIndex++; if(psIndex > PO_MAXPOLYSEGS) { I_Error("SpawnPolyobj: psIndex > PO_MAXPOLYSEGS\n"); } } } } // Clear out any specials for these segs...we cannot clear them out // in the above loop, since we aren't guaranteed one seg per // linedef. for(i = 0; i < numsegs; i++) { if(segs[i].linedef->special == PO_LINE_EXPLICIT && segs[i].linedef->arg1 == tag && segs[i].linedef->arg2 == j) { segs[i].linedef->special = 0; segs[i].linedef->arg1 = 0; } } if(psIndex == psIndexOld) { // Check if an explicit line order has been skipped // A line has been skipped if there are any more explicit // lines with the current tag value for(i = 0; i < numsegs; i++) { if(segs[i].linedef->special == PO_LINE_EXPLICIT && segs[i].linedef->arg1 == tag) { I_Error("SpawnPolyobj: Missing explicit line %d for poly %d\n", j, tag); } } } } if(polyobjs[index].numsegs) { PolySegCount = polyobjs[index].numsegs; // PolySegCount used globally polyobjs[index].crush = crush; polyobjs[index].tag = tag; polyobjs[index].segs = Z_Malloc(polyobjs[index].numsegs *sizeof(seg_t *), PU_LEVEL, 0); for(i = 0; i < polyobjs[index].numsegs; i++) { polyobjs[index].segs[i] = polySegList[i]; } polyobjs[index].seqType = (*polyobjs[index].segs)->linedef->arg4; } // Next, change the polyobjs first line to point to a mirror // if it exists (*polyobjs[index].segs)->linedef->arg2 = (*polyobjs[index].segs)->linedef->arg3; }}//==========================================================================//// TranslateToStartSpot////==========================================================================static void TranslateToStartSpot(int tag, int originX, int originY){ seg_t **tempSeg; seg_t **veryTempSeg; vertex_t *tempPt; subsector_t *sub; polyobj_t *po; int deltaX; int deltaY; vertex_t avg; // used to find a polyobj's center, and hence subsector int i; po = NULL; for(i = 0; i < po_NumPolyobjs; i++) { if(polyobjs[i].tag == tag) { po = &polyobjs[i]; break; } } if(!po) { // didn't match the tag with a polyobj tag I_Error("TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); } if(po->segs == NULL) { I_Error("TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); } po->originalPts = Z_Malloc(po->numsegs*sizeof(vertex_t), PU_LEVEL, 0); po->prevPts = Z_Malloc(po->numsegs*sizeof(vertex_t), PU_LEVEL, 0); deltaX = originX-po->startSpot.x; deltaY = originY-po->startSpot.y; tempSeg = po->segs; tempPt = po->originalPts; avg.x = 0; avg.y = 0; validcount++; for(i = 0; i < po->numsegs; i++, tempSeg++, tempPt++) { if((*tempSeg)->linedef->validcount != validcount) { (*tempSeg)->linedef->bbox[BOXTOP] -= deltaY; (*tempSeg)->linedef->bbox[BOXBOTTOM] -= deltaY; (*tempSeg)->linedef->bbox[BOXLEFT] -= deltaX; (*tempSeg)->linedef->bbox[BOXRIGHT] -= deltaX; (*tempSeg)->linedef->validcount = validcount; } for(veryTempSeg = po->segs; veryTempSeg != tempSeg; veryTempSeg++) { if((*veryTempSeg)->v1 == (*tempSeg)->v1) { break; } } if(veryTempSeg == tempSeg) { // the point hasn't been translated, yet (*tempSeg)->v1->x -= deltaX; (*tempSeg)->v1->y -= deltaY; } avg.x += (*tempSeg)->v1->x>>FRACBITS; avg.y += (*tempSeg)->v1->y>>FRACBITS; // the original Pts are based off the startSpot Pt, and are // unique to each seg, not each linedef tempPt->x = (*tempSeg)->v1->x-po->startSpot.x; tempPt->y = (*tempSeg)->v1->y-po->startSpot.y; } avg.x /= po->numsegs; avg.y /= po->numsegs; sub = R_PointInSubsector(avg.x<<FRACBITS, avg.y<<FRACBITS); if(sub->poly != NULL) { I_Error("PO_TranslateToStartSpot: Multiple polyobjs in a single subsector.\n"); } sub->poly = po;}//==========================================================================//// PO_Init////==========================================================================void PO_Init(int lump){ byte *data; int i; mapthing_t *mt; int numthings; int polyIndex; polyobjs = Z_Malloc(po_NumPolyobjs*sizeof(polyobj_t), PU_LEVEL, 0); memset(polyobjs, 0, po_NumPolyobjs*sizeof(polyobj_t)); data = W_CacheLumpNum(lump, PU_STATIC); numthings = W_LumpLength(lump)/sizeof(mapthing_t); mt = (mapthing_t *)data; polyIndex = 0; // index polyobj number // Find the startSpot points, and spawn each polyobj for (i = 0; i < numthings; i++, mt++) { mt->x = SHORT(mt->x); mt->y = SHORT(mt->y); mt->angle = SHORT(mt->angle); mt->type = SHORT(mt->type); // 3001 = no crush, 3002 = crushing if(mt->type == PO_SPAWN_TYPE || mt->type == PO_SPAWNCRUSH_TYPE) { // Polyobj StartSpot Pt. polyobjs[polyIndex].startSpot.x = mt->x<<FRACBITS; polyobjs[polyIndex].startSpot.y = mt->y<<FRACBITS; SpawnPolyobj(polyIndex, mt->angle, (mt->type == PO_SPAWNCRUSH_TYPE)); polyIndex++; } } mt = (mapthing_t *)data; for (i = 0; i < numthings; i++, mt++) { mt->x = SHORT(mt->x); mt->y = SHORT(mt->y); mt->angle = SHORT(mt->angle); mt->type = SHORT(mt->type); if(mt->type == PO_ANCHOR_TYPE) { // Polyobj Anchor Pt. TranslateToStartSpot(mt->angle, mt->x<<FRACBITS, mt->y<<FRACBITS); } } Z_Free (data); // check for a startspot without an anchor point for(i = 0; i < po_NumPolyobjs; i++) { if(!polyobjs[i].originalPts) { I_Error("PO_Init: StartSpot located without an Anchor point: %d\n", polyobjs[i].tag); } } InitBlockMap();}//==========================================================================//// PO_Busy////==========================================================================boolean PO_Busy(int polyobj){ polyobj_t *poly; poly = GetPolyobj(polyobj); if(!poly->specialdata) { return false; } else { return true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -