// multiple turrets display removed the pointless mountRotation void displayComponentObject(DROID *psDroid, const glm::mat4 &viewMatrix) { Vector3i position, rotation; Spacetime st = interpolateObjectSpacetime(psDroid, graphicsTime); leftFirst = angleDelta(player.r.y - st.rot.direction) <= 0; /* Get the real position */ position.x = st.pos.x - player.p.x; position.z = -(st.pos.y - player.p.z); position.y = st.pos.z; if (isTransporter(psDroid)) { position.y += bobTransporterHeight(); } /* Get all the pitch,roll,yaw info */ rotation.y = -st.rot.direction; rotation.x = st.rot.pitch; rotation.z = st.rot.roll; /* Translate origin */ /* Rotate for droid */ glm::mat4 modelMatrix = glm::translate(glm::vec3(position)) * glm::rotate(UNDEG(rotation.y), glm::vec3(0.f, 1.f, 0.f)) * glm::rotate(UNDEG(rotation.x), glm::vec3(1.f, 0.f, 0.f)) * glm::rotate(UNDEG(rotation.z), glm::vec3(0.f, 0.f, 1.f)); if (graphicsTime - psDroid->timeLastHit < GAME_TICKS_PER_SEC && psDroid->lastHitWeapon == WSC_ELECTRONIC) { modelMatrix *= objectShimmy((BASE_OBJECT *) psDroid); } // now check if the projected circle is within the screen boundaries if(!clipDroidOnScreen(psDroid, viewMatrix * modelMatrix)) { return; } if (psDroid->lastHitWeapon == WSC_EMP && graphicsTime - psDroid->timeLastHit < EMP_DISABLE_TIME) { Vector3i position; //add an effect on the droid position.x = st.pos.x + DROID_EMP_SPREAD; position.y = st.pos.z + rand() % 8; position.z = st.pos.y + DROID_EMP_SPREAD; effectGiveAuxVar(90 + rand() % 20); addEffect(&position, EFFECT_EXPLOSION, EXPLOSION_TYPE_PLASMA, false, nullptr, 0); } if (psDroid->visible[selectedPlayer] == UBYTE_MAX) { //ingame not button object //should render 3 mounted weapons now if (displayCompObj(psDroid, false, viewMatrix * modelMatrix)) { // did draw something to the screen - update the framenumber psDroid->sDisplay.frameNumber = frameGetFrameNumber(); } } else { int frame = graphicsTime / BLIP_ANIM_DURATION + psDroid->id % 8192; // de-sync the blip effect, but don't overflow the int if (pie_Draw3DShape(getImdFromIndex(MI_BLIP), frame, 0, WZCOL_WHITE, pie_ADDITIVE, psDroid->visible[selectedPlayer] / 2, viewMatrix * modelMatrix)) { psDroid->sDisplay.frameNumber = frameGetFrameNumber(); } } }
static SDWORD bucketCalculateZ(RENDER_TYPE objectType, void* pObject) { SDWORD z = 0, radius; SDWORD px, pz; Vector2i pixel; Vector3i position; UDWORD droidSize; DROID *psDroid; BODY_STATS *psBStats; SIMPLE_OBJECT *psSimpObj; COMPONENT_OBJECT *psCompObj; const iIMDShape *pImd; Spacetime spacetime; pie_MatBegin(); switch(objectType) { case RENDER_PARTICLE: px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); position.x = ((ATPART*)pObject)->position.x; position.y = ((ATPART*)pObject)->position.y; position.z = ((ATPART*)pObject)->position.z; position.x = (SDWORD)(position.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = (SDWORD)(terrainMidY*TILE_UNITS - (position.z - player.p.z)); position.y = (SDWORD)position.y; /* 16 below is HACK!!! */ z = pie_RotateProject(&position,&pixel) - 16; if (z > 0) { //particle use the image radius radius = ((ATPART*)pObject)->imd->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; case RENDER_PROJECTILE: if(((PROJECTILE*)pObject)->psWStats->weaponSubClass == WSC_FLAME || ((PROJECTILE*)pObject)->psWStats->weaponSubClass == WSC_COMMAND || ((PROJECTILE*)pObject)->psWStats->weaponSubClass == WSC_EMP) { /* We don't do projectiles from these guys, cos there's an effect instead */ z = -1; } else { //the weapon stats holds the reference to which graphic to use pImd = ((PROJECTILE*)pObject)->psWStats->pInFlightGraphic; px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); psSimpObj = (SIMPLE_OBJECT*) pObject; position.x = (psSimpObj->pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (psSimpObj->pos.y - player.p.z); position.y = psSimpObj->pos.z; z = pie_RotateProject(&position,&pixel); if (z > 0) { //particle use the image radius radius = pImd->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } } break; case RENDER_STRUCTURE://not depth sorted px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); psSimpObj = (SIMPLE_OBJECT*) pObject; position.x = (psSimpObj->pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (psSimpObj->pos.y - player.p.z); //if((objectType == RENDER_STRUCTURE) && (((STRUCTURE*)pObject)-> // pStructureType->type >= REF_DEFENSE) && // (((STRUCTURE*)pObject)->pStructureType->type<=REF_TOWER4)) if((objectType == RENDER_STRUCTURE) && ((((STRUCTURE*)pObject)->pStructureType->type == REF_DEFENSE) || (((STRUCTURE*)pObject)->pStructureType->type == REF_WALL) || (((STRUCTURE*)pObject)->pStructureType->type == REF_WALLCORNER))) { position.y = psSimpObj->pos.z + 64; radius = ((STRUCTURE*)pObject)->sDisplay.imd->radius;//walls guntowers and tank traps clip tightly } else { position.y = psSimpObj->pos.z; radius = (((STRUCTURE*)pObject)->sDisplay.imd->radius); } z = pie_RotateProject(&position,&pixel); if (z > 0) { //particle use the image radius radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; case RENDER_FEATURE://not depth sorted px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); psSimpObj = (SIMPLE_OBJECT*) pObject; position.x = (psSimpObj->pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (psSimpObj->pos.y - player.p.z); position.y = psSimpObj->pos.z+2; z = pie_RotateProject(&position,&pixel); if (z > 0) { //particle use the image radius radius = ((FEATURE*)pObject)->sDisplay.imd->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; case RENDER_ANIMATION://not depth sorted px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); psCompObj = (COMPONENT_OBJECT *) pObject; spacetime = interpolateObjectSpacetime((SIMPLE_OBJECT *)psCompObj->psParent, graphicsTime); position.x = (spacetime.pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (spacetime.pos.y - player.p.z); position.y = spacetime.pos.z; /* object offset translation */ position.x += psCompObj->psShape->ocen.x; position.y += psCompObj->psShape->ocen.z; position.z -= psCompObj->psShape->ocen.y; /* object (animation) translations - ivis z and y flipped */ pie_TRANSLATE( psCompObj->position.x, psCompObj->position.z, psCompObj->position.y ); /* object (animation) rotations */ pie_MatRotY(-psCompObj->orientation.z); pie_MatRotZ(-psCompObj->orientation.y); pie_MatRotX(-psCompObj->orientation.x); z = pie_RotateProject(&position,&pixel); break; case RENDER_DROID: case RENDER_SHADOW: psDroid = (DROID*) pObject; px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); psSimpObj = (SIMPLE_OBJECT*) pObject; position.x = (psSimpObj->pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (psSimpObj->pos.y - player.p.z); position.y = psSimpObj->pos.z; if(objectType == RENDER_SHADOW) { position.y+=4; } psBStats = asBodyStats + psDroid->asBits[COMP_BODY].nStat; droidSize = psBStats->pIMD->radius; z = pie_RotateProject(&position,&pixel) - (droidSize*2); if (z > 0) { //particle use the image radius radius = droidSize; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; case RENDER_PROXMSG: px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); if (((PROXIMITY_DISPLAY *)pObject)->type == POS_PROXDATA) { position.x = (((VIEW_PROXIMITY *)((VIEWDATA *)((PROXIMITY_DISPLAY *) pObject)->psMessage->pViewData)->pData)->x - player.p.x) - terrainMidX * TILE_UNITS; position.z = terrainMidY * TILE_UNITS - (((VIEW_PROXIMITY *)((VIEWDATA *) ((PROXIMITY_DISPLAY *)pObject)->psMessage->pViewData)->pData)->y - player.p.z); position.y = ((VIEW_PROXIMITY *)((VIEWDATA *)((PROXIMITY_DISPLAY *)pObject)-> psMessage->pViewData)->pData)->z; } else if (((PROXIMITY_DISPLAY *)pObject)->type == POS_PROXOBJ) { position.x = (((BASE_OBJECT *)((PROXIMITY_DISPLAY *)pObject)-> psMessage->pViewData)->pos.x - player.p.x) - terrainMidX * TILE_UNITS; position.z = terrainMidY * TILE_UNITS - (((BASE_OBJECT *)(( PROXIMITY_DISPLAY *)pObject)->psMessage->pViewData)->pos.y - player.p.z); position.y = ((BASE_OBJECT *)((PROXIMITY_DISPLAY *)pObject)-> psMessage->pViewData)->pos.z; } z = pie_RotateProject(&position,&pixel); if (z > 0) { //particle use the image radius pImd = getImdFromIndex(MI_BLIP_ENEMY);//use MI_BLIP_ENEMY as all are same radius radius = pImd->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; case RENDER_EFFECT: px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); position.x = (SDWORD)(((EFFECT*)pObject)->position.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = (SDWORD)(terrainMidY*TILE_UNITS - (((EFFECT*)pObject)->position.z - player.p.z)); position.y = (SDWORD)((EFFECT*)pObject)->position.y; /* 16 below is HACK!!! */ z = pie_RotateProject(&position,&pixel) - 16; if (z > 0) { //particle use the image radius pImd = ((EFFECT*)pObject)->imd; if (pImd != NULL) { radius = pImd->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } } break; case RENDER_DELIVPOINT: px = player.p.x & (TILE_UNITS-1); pz = player.p.z & (TILE_UNITS-1); /* Translate */ pie_TRANSLATE(px,0,-pz); position.x = (((FLAG_POSITION *)pObject)->coords.x - player.p.x) - terrainMidX * TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (((FLAG_POSITION*)pObject)-> coords.y - player.p.z); position.y = ((FLAG_POSITION*)pObject)->coords.z; z = pie_RotateProject(&position,&pixel); if (z > 0) { //particle use the image radius radius = pAssemblyPointIMDs[((FLAG_POSITION*)pObject)->factoryType][((FLAG_POSITION*)pObject)->factoryInc]->radius; radius *= SCALE_DEPTH; radius /= z; if ((pixel.x + radius < CLIP_LEFT) || (pixel.x - radius > CLIP_RIGHT) || (pixel.y + radius < CLIP_TOP) || (pixel.y - radius > CLIP_BOTTOM)) { z = -1; } } break; default: break; } pie_MatEnd(); return z; }
// this is able to handle multiple weapon graphics now // removed mountRotation,they get such stuff from psObj directly now static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4 &viewMatrix) { iIMDShape *psMoveAnim, *psStillAnim; SDWORD iConnector; PROPULSION_STATS *psPropStats; SDWORD pieFlag, iPieData; PIELIGHT brightness; UDWORD colour; UBYTE i; bool didDrawSomething = false; glm::mat4 modelMatrix(1.f); if (graphicsTime - psDroid->timeLastHit < GAME_TICKS_PER_SEC / 4 && psDroid->lastHitWeapon == WSC_ELECTRONIC && !gamePaused()) { colour = getPlayerColour(rand() % MAX_PLAYERS); } else { colour = getPlayerColour(psDroid->player); } /* get propulsion stats */ psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; ASSERT_OR_RETURN(didDrawSomething, psPropStats != nullptr, "invalid propulsion stats pointer"); //set pieflag for button object or ingame object if (bButton) { pieFlag = pie_BUTTON; brightness = WZCOL_WHITE; } else { pieFlag = pie_SHADOW; brightness = pal_SetBrightness(psDroid->illumination); // NOTE: Beware of transporters that are offscreen, on a mission! We should *not* be checking tiles at this point in time! if (!isTransporter(psDroid) && !missionIsOffworld()) { MAPTILE *psTile = worldTile(psDroid->pos.x, psDroid->pos.y); if (psTile->jammerBits & alliancebits[psDroid->player]) { pieFlag |= pie_ECM; } } } /* set default components transparent */ if (psDroid->asBits[COMP_PROPULSION] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { iPieData = 0; } if (!bButton && psPropStats->propulsionType == PROPULSION_TYPE_PROPELLOR) { // FIXME: change when adding submarines to the game modelMatrix *= glm::translate(glm::vec3(0.f, -world_coord(1) / 2.3f, 0.f)); } iIMDShape *psShapeProp = (leftFirst ? getLeftPropulsionIMD(psDroid) : getRightPropulsionIMD(psDroid)); if (psShapeProp) { if (pie_Draw3DShape(psShapeProp, 0, colour, brightness, pieFlag, iPieData, viewMatrix * modelMatrix)) { didDrawSomething = true; } } /* set default components transparent */ if (psDroid->asBits[COMP_BODY] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } /* Get the body graphic now*/ iIMDShape *psShapeBody = BODY_IMD(psDroid, psDroid->player); if (psShapeBody) { iIMDShape *strImd = psShapeBody; if (psDroid->droidType == DROID_PERSON) { modelMatrix *= glm::scale(glm::vec3(.75f)); // FIXME - hideous....!!!! } if (strImd->objanimpie[psDroid->animationEvent]) { strImd = psShapeBody->objanimpie[psDroid->animationEvent]; } glm::mat4 viewModelMatrix = viewMatrix * modelMatrix; while (strImd) { if (drawShape(psDroid, strImd, colour, brightness, pieFlag, iPieData, viewModelMatrix)) { didDrawSomething = true; } strImd = strImd->next; } } /* Render animation effects based on movement or lack thereof, if any */ psMoveAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppMoveIMDList[psDroid->asBits[COMP_PROPULSION]]; psStillAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppStillIMDList[psDroid->asBits[COMP_PROPULSION]]; glm::mat4 viewModelMatrix = viewMatrix * modelMatrix; if (!bButton && psMoveAnim && psDroid->sMove.Status != MOVEINACTIVE) { if (pie_Draw3DShape(psMoveAnim, getModularScaledGraphicsTime(psMoveAnim->animInterval, psMoveAnim->numFrames), colour, brightness, pie_ADDITIVE, 200, viewModelMatrix)) { didDrawSomething = true; } } else if (!bButton && psStillAnim) // standing still { if (pie_Draw3DShape(psStillAnim, getModularScaledGraphicsTime(psStillAnim->animInterval, psStillAnim->numFrames), colour, brightness, 0, 0, viewModelMatrix)) { didDrawSomething = true; } } //don't change the screen coords of an object if drawing it in a button if (!bButton) { /* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */ calcScreenCoords(psDroid, viewModelMatrix); } /* set default components transparent */ if (psDroid->asWeaps[0].nStat == 0 && psDroid->asBits[COMP_SENSOR] == 0 && psDroid->asBits[COMP_ECM] == 0 && psDroid->asBits[COMP_BRAIN] == 0 && psDroid->asBits[COMP_REPAIRUNIT] == 0 && psDroid->asBits[COMP_CONSTRUCT] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } if (psShapeBody && psShapeBody->nconnectors) { /* vtol weapons attach to connector 2 (underneath); * all others to connector 1 */ /* VTOL's now skip the first 5 connectors(0 to 4), VTOL's use 5,6,7,8 etc now */ if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT && psDroid->droidType == DROID_WEAPON) { iConnector = VTOL_CONNECTOR_START; } else { iConnector = 0; } switch (psDroid->droidType) { case DROID_DEFAULT: case DROID_TRANSPORTER: case DROID_SUPERTRANSPORTER: case DROID_CYBORG: case DROID_CYBORG_SUPER: case DROID_WEAPON: case DROID_COMMAND: // command droids have a weapon to store all the graphics /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ /* Double check that the weapon droid actually has any */ for (i = 0; i < psDroid->numWeaps; i++) { if ((psDroid->asWeaps[i].nStat > 0 || psDroid->droidType == DROID_DEFAULT) && psShapeBody->connectors) { Rotation rot = getInterpolatedWeaponRotation(psDroid, i, graphicsTime); glm::mat4 localModelMatrix = modelMatrix; //to skip number of VTOL_CONNECTOR_START ground unit connectors if (iConnector < VTOL_CONNECTOR_START) { localModelMatrix *= glm::translate(glm::vec3(psShapeBody->connectors[i].xzy())); } else { localModelMatrix *= glm::translate(glm::vec3(psShapeBody->connectors[iConnector + i].xzy())); } localModelMatrix *= glm::rotate(UNDEG(-rot.direction), glm::vec3(0.f, 1.f, 0.f)); /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { //this might affect gun rotation localModelMatrix *= glm::rotate(UNDEG(65536 / 2), glm::vec3(0.f, 0.f, 1.f)); } /* Get the mount graphic */ iIMDShape *psShape = WEAPON_MOUNT_IMD(psDroid, i); int recoilValue = getRecoil(psDroid->asWeaps[i]); localModelMatrix *= glm::translate(glm::vec3(0.f, 0.f, recoilValue / 3.f)); /* Draw it */ if (psShape) { if (pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData, viewMatrix * localModelMatrix)) { didDrawSomething = true; } } localModelMatrix *= glm::translate(glm::vec3(0, 0, recoilValue)); /* translate for weapon mount point */ if (psShape && psShape->nconnectors) { localModelMatrix *= glm::translate(glm::vec3(psShape->connectors->xzy())); } /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { //pitch the barrel down localModelMatrix *= glm::rotate(UNDEG(-rot.pitch), glm::vec3(1.f, 0.f, 0.f)); } else { //pitch the barrel up localModelMatrix *= glm::rotate(UNDEG(rot.pitch), glm::vec3(1.f, 0.f, 0.f)); } /* Get the weapon (gun?) graphic */ psShape = WEAPON_IMD(psDroid, i); // We have a weapon so we draw it and a muzzle flash from weapon connector if (psShape) { glm::mat4 localViewModelMatrix = viewMatrix * localModelMatrix; if (pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData, localViewModelMatrix)) { didDrawSomething = true; } drawMuzzleFlash(psDroid->asWeaps[i], psShape, MUZZLE_FLASH_PIE(psDroid, i), brightness, pieFlag, iPieData, localViewModelMatrix); } } } break; case DROID_SENSOR: case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: case DROID_ECM: case DROID_REPAIR: case DROID_CYBORG_REPAIR: { Rotation rot = getInterpolatedWeaponRotation(psDroid, 0, graphicsTime); iIMDShape *psShape = nullptr; iIMDShape *psMountShape = nullptr; switch (psDroid->droidType) { default: ASSERT(false, "Bad component type"); break; case DROID_SENSOR: psMountShape = SENSOR_MOUNT_IMD(psDroid, psDroid->player); /* Get the sensor graphic, assuming it's there */ psShape = SENSOR_IMD(psDroid, psDroid->player); break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: psMountShape = CONSTRUCT_MOUNT_IMD(psDroid, psDroid->player); /* Get the construct graphic assuming it's there */ psShape = CONSTRUCT_IMD(psDroid, psDroid->player); break; case DROID_ECM: psMountShape = ECM_MOUNT_IMD(psDroid, psDroid->player); /* Get the ECM graphic assuming it's there.... */ psShape = ECM_IMD(psDroid, psDroid->player); break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: psMountShape = REPAIR_MOUNT_IMD(psDroid, psDroid->player); /* Get the Repair graphic assuming it's there.... */ psShape = REPAIR_IMD(psDroid, psDroid->player); break; } /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ //sensor and cyborg and ecm uses connectors[0] glm::mat4 localModelMatrix = modelMatrix; /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { //this might affect gun rotation localModelMatrix *= glm::rotate(UNDEG(65536 / 2), glm::vec3(0.f, 0.f, 1.f)); } localModelMatrix *= glm::translate(glm::vec3(psShapeBody->connectors[0].xzy())); localModelMatrix *= glm::rotate(UNDEG(-rot.direction), glm::vec3(0.f, 1.f, 0.f)); /* Draw it */ if (psMountShape) { if (pie_Draw3DShape(psMountShape, 0, colour, brightness, pieFlag, iPieData, viewMatrix * localModelMatrix)) { didDrawSomething = true; } } /* translate for construct mount point if cyborg */ if (cyborgDroid(psDroid) && psMountShape && psMountShape->nconnectors) { localModelMatrix *= glm::translate(glm::vec3(psMountShape->connectors[0].xzy())); } /* Draw it */ if (psShape) { if (pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData, viewMatrix * localModelMatrix)) { didDrawSomething = true; } // In repair droid case only: if ((psDroid->droidType == DROID_REPAIR || psDroid->droidType == DROID_CYBORG_REPAIR) && psShape->nconnectors && psDroid->action == DACTION_DROIDREPAIR) { Spacetime st = interpolateObjectSpacetime(psDroid, graphicsTime); localModelMatrix *= glm::translate(glm::vec3(psShape->connectors[0].xzy())); localModelMatrix *= glm::translate(glm::vec3(0.f, -20.f, 0.f)); psShape = getImdFromIndex(MI_FLAME); /* Rotate for droid */ localModelMatrix *= glm::rotate(UNDEG(st.rot.direction), glm::vec3(0.f, 1.f, 0.f)); localModelMatrix *= glm::rotate(UNDEG(-st.rot.pitch), glm::vec3(1.f, 0.f, 0.f)); localModelMatrix *= glm::rotate(UNDEG(-st.rot.roll), glm::vec3(0.f, 0.f, 1.f)); //rotate Y localModelMatrix *= glm::rotate(UNDEG(rot.direction), glm::vec3(0.f, 1.f, 0.f)); localModelMatrix *= glm::rotate(UNDEG(-player.r.y), glm::vec3(0.f, 1.f, 0.f)); localModelMatrix *= glm::rotate(UNDEG(-player.r.x), glm::vec3(1.f, 0.f, 0.f)); if (pie_Draw3DShape(psShape, getModularScaledGraphicsTime(psShape->animInterval, psShape->numFrames), 0, brightness, pie_ADDITIVE, 140, viewMatrix * localModelMatrix)) { didDrawSomething = true; } // localModelMatrix *= glm::rotate(UNDEG(player.r.x), glm::vec3(1.f, 0.f, 0.f)); // Not used? // localModelMatrix *= glm::rotate(UNDEG(player.r.y), glm::vec3(0.f, 1.f, 0.f)); // Not used? } } break; } case DROID_PERSON: // no extra mounts for people break; default: ASSERT(!"invalid droid type", "Whoa! Weirdy type of droid found in drawComponentObject!!!"); break; } } /* set default components transparent */ if (psDroid->asBits[COMP_PROPULSION] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } // now render the other propulsion side psShapeProp = (leftFirst ? getRightPropulsionIMD(psDroid) : getLeftPropulsionIMD(psDroid)); if (psShapeProp) { if (pie_Draw3DShape(psShapeProp, 0, colour, brightness, pieFlag, iPieData, viewModelMatrix)) // Safe to use viewModelMatrix because modelView has not been changed since it was calculated { didDrawSomething = true; } } return didDrawSomething; }
// multiple turrets display removed the pointless mountRotation void displayComponentObject(DROID *psDroid) { Vector3i position, rotation; Spacetime st = interpolateObjectSpacetime(psDroid, graphicsTime); leftFirst = angleDelta(player.r.y - st.rot.direction) <= 0; /* Push the matrix */ pie_MatBegin(true); /* Get the real position */ position.x = st.pos.x - player.p.x; position.z = -(st.pos.y - player.p.z); position.y = st.pos.z; if (isTransporter(psDroid)) { position.y += bobTransporterHeight(); } /* Get all the pitch,roll,yaw info */ rotation.y = -st.rot.direction; rotation.x = st.rot.pitch; rotation.z = st.rot.roll; /* Translate origin */ pie_TRANSLATE(position.x, position.y, position.z); /* Rotate for droid */ pie_MatRotY(rotation.y); pie_MatRotX(rotation.x); pie_MatRotZ(rotation.z); if (graphicsTime - psDroid->timeLastHit < GAME_TICKS_PER_SEC && psDroid->lastHitWeapon == WSC_ELECTRONIC) { objectShimmy((BASE_OBJECT *) psDroid); } if (psDroid->lastHitWeapon == WSC_EMP && graphicsTime - psDroid->timeLastHit < EMP_DISABLE_TIME) { Vector3i position; //add an effect on the droid position.x = st.pos.x + DROID_EMP_SPREAD; position.y = st.pos.z + rand() % 8; position.z = st.pos.y + DROID_EMP_SPREAD; effectGiveAuxVar(90 + rand() % 20); addEffect(&position, EFFECT_EXPLOSION, EXPLOSION_TYPE_PLASMA, false, NULL, 0); } if (psDroid->visible[selectedPlayer] == UBYTE_MAX) { //ingame not button object //should render 3 mounted weapons now displayCompObj(psDroid, false); } else { int frame = graphicsTime / BLIP_ANIM_DURATION + psDroid->id % 8192; // de-sync the blip effect, but don't overflow the int pie_Draw3DShape(getImdFromIndex(MI_BLIP), frame, 0, WZCOL_WHITE, pie_ADDITIVE, psDroid->visible[selectedPlayer] / 2); } pie_MatEnd(); }
// this is able to handle multiple weapon graphics now // removed mountRotation,they get such stuff from psObj directly now static void displayCompObj(DROID *psDroid, bool bButton) { iIMDShape *psShape, *psMoveAnim, *psStillAnim, *psShapeTemp = NULL, *psMountShape; SDWORD iConnector; PROPULSION_STATS *psPropStats; SDWORD pieFlag, iPieData; PIELIGHT brightness; UDWORD colour; UBYTE i; if (graphicsTime - psDroid->timeLastHit < GAME_TICKS_PER_SEC / 4 && psDroid->lastHitWeapon == WSC_ELECTRONIC && !gamePaused()) { colour = getPlayerColour(rand() % MAX_PLAYERS); } else { colour = getPlayerColour(psDroid->player); } /* get propulsion stats */ psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; ASSERT_OR_RETURN(, psPropStats != NULL, "invalid propulsion stats pointer"); //set pieflag for button object or ingame object if (bButton) { pieFlag = pie_BUTTON; brightness = WZCOL_WHITE; } else { pieFlag = pie_SHADOW; brightness = pal_SetBrightness(psDroid->illumination); // NOTE: Beware of transporters that are offscreen, on a mission! We should *not* be checking tiles at this point in time! if (!isTransporter(psDroid) && !missionIsOffworld()) { MAPTILE *psTile = worldTile(psDroid->pos.x, psDroid->pos.y); if (psTile->jammerBits & alliancebits[psDroid->player]) { pieFlag |= pie_ECM; } } } /* set default components transparent */ if (psDroid->asBits[COMP_PROPULSION] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { iPieData = 0; } if (!bButton && psPropStats->propulsionType == PROPULSION_TYPE_PROPELLOR) { // FIXME: change when adding submarines to the game pie_TRANSLATE(0, -world_coord(1) / 2.3f, 0); } //uses psShapeTemp too separate it from turret's psShape psShapeTemp = (leftFirst ? getLeftPropulsionIMD(psDroid) : getRightPropulsionIMD(psDroid)); if (psShapeTemp != NULL) { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, pieFlag, iPieData); } /* set default components transparent */ if (psDroid->asBits[COMP_BODY] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } /* Get the body graphic now*/ //uses psShapeTemp too separate it from turret's psShape psShapeTemp = BODY_IMD(psDroid, psDroid->player); if (psShapeTemp != NULL) { // FIXME if (psDroid->droidType == DROID_PERSON) { /* draw body if not animating */ if (psDroid->psCurAnim == NULL || psDroid->psCurAnim->bVisible == false) { // FIXME - hideous....!!!! pie_MatScale(.75f); pie_Draw3DShape(psShapeTemp, 0, psDroid->player - 6, brightness, pieFlag, iPieData); } } else if (cyborgDroid(psDroid)) { /* draw body if cyborg not animating */ if (psDroid->psCurAnim == NULL || psDroid->psCurAnim->bVisible == false) { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, pieFlag, iPieData); } } else { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, pieFlag, iPieData); } } /* Render animation effects based on movement or lack thereof, if any */ psMoveAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppMoveIMDList[psDroid->asBits[COMP_PROPULSION]]; psStillAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppStillIMDList[psDroid->asBits[COMP_PROPULSION]]; if (!bButton && psMoveAnim && psDroid->sMove.Status != MOVEINACTIVE) { pie_Draw3DShape(psMoveAnim, getModularScaledGraphicsTime(psMoveAnim->animInterval, psMoveAnim->numFrames), colour, brightness, pie_ADDITIVE, 200); } else if (!bButton && psStillAnim) // standing still { pie_Draw3DShape(psStillAnim, getModularScaledGraphicsTime(psStillAnim->animInterval, psStillAnim->numFrames), colour, brightness, 0, 0); } //don't change the screen coords of an object if drawing it in a button if (!bButton) { /* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */ calcScreenCoords(psDroid); } /* set default components transparent */ if (psDroid->asWeaps[0].nStat == 0 && psDroid->asBits[COMP_SENSOR] == 0 && psDroid->asBits[COMP_ECM] == 0 && psDroid->asBits[COMP_BRAIN] == 0 && psDroid->asBits[COMP_REPAIRUNIT] == 0 && psDroid->asBits[COMP_CONSTRUCT] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } psShapeTemp = BODY_IMD(psDroid, psDroid->player); if (psShapeTemp->nconnectors) { /* vtol weapons attach to connector 2 (underneath); * all others to connector 1 */ /* VTOL's now skip the first 5 connectors(0 to 4), VTOL's use 5,6,7,8 etc now */ if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT && psDroid->droidType == DROID_WEAPON) { iConnector = VTOL_CONNECTOR_START; } else { iConnector = 0; } switch (psDroid->droidType) { case DROID_DEFAULT: case DROID_TRANSPORTER: case DROID_SUPERTRANSPORTER: case DROID_CYBORG: case DROID_CYBORG_SUPER: case DROID_WEAPON: case DROID_COMMAND: // command droids have a weapon to store all the graphics /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ /* Double check that the weapon droid actually has any */ for (i = 0; i < psDroid->numWeaps; i++) { if ((psDroid->asWeaps[i].nStat > 0 || psDroid->droidType == DROID_DEFAULT) && psShapeTemp->connectors) { Rotation rot = getInterpolatedWeaponRotation(psDroid, i, graphicsTime); pie_MatBegin(!bButton); //to skip number of VTOL_CONNECTOR_START ground unit connectors if (iConnector < VTOL_CONNECTOR_START) { pie_TRANSLATE(psShapeTemp->connectors[i].x, psShapeTemp->connectors[i].z, psShapeTemp->connectors[i].y); } else { pie_TRANSLATE(psShapeTemp->connectors[iConnector + i].x, psShapeTemp->connectors[iConnector + i].z, psShapeTemp->connectors[iConnector + i].y); } pie_MatRotY(-rot.direction); /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { pie_MatRotZ(65536 / 2); //this might affect gun rotation } /* Get the mount graphic */ psShape = WEAPON_MOUNT_IMD(psDroid, i); int recoilValue = getRecoil(psDroid->asWeaps[i]); pie_TRANSLATE(0, 0, recoilValue / 3); /* Draw it */ if (psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData); } pie_TRANSLATE(0, 0, recoilValue); /* translate for weapon mount point */ if (psShape && psShape->nconnectors) { pie_TRANSLATE(psShape->connectors->x, psShape->connectors->z, psShape->connectors->y); } /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { //pitch the barrel down pie_MatRotX(-rot.pitch); } else { //pitch the barrel up pie_MatRotX(rot.pitch); } /* Get the weapon (gun?) graphic */ psShape = WEAPON_IMD(psDroid, i); // We have a weapon so we draw it and a muzzle flash from weapon connector if (psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData); drawMuzzleFlash(psDroid->asWeaps[i], psShape, MUZZLE_FLASH_PIE(psDroid, i), brightness, pieFlag, iPieData); } /* Pop Matrix */ pie_MatEnd(); } } break; case DROID_SENSOR: case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: case DROID_ECM: case DROID_REPAIR: case DROID_CYBORG_REPAIR: { Rotation rot = getInterpolatedWeaponRotation(psDroid, 0, graphicsTime); switch (psDroid->droidType) { default: ASSERT(false, "..."); case DROID_SENSOR: psMountShape = SENSOR_MOUNT_IMD(psDroid, psDroid->player); /* Get the sensor graphic, assuming it's there */ psShape = SENSOR_IMD(psDroid, psDroid->player); break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: psMountShape = CONSTRUCT_MOUNT_IMD(psDroid, psDroid->player); /* Get the construct graphic assuming it's there */ psShape = CONSTRUCT_IMD(psDroid, psDroid->player); break; case DROID_ECM: psMountShape = ECM_MOUNT_IMD(psDroid, psDroid->player); /* Get the ECM graphic assuming it's there.... */ psShape = ECM_IMD(psDroid, psDroid->player); break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: psMountShape = REPAIR_MOUNT_IMD(psDroid, psDroid->player); /* Get the Repair graphic assuming it's there.... */ psShape = REPAIR_IMD(psDroid, psDroid->player); break; } /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ //sensor and cyborg and ecm uses connectors[0] pie_MatBegin(!bButton); /* vtol weapons inverted */ if (iConnector >= VTOL_CONNECTOR_START) { pie_MatRotZ(65536 / 2); //this might affect gun rotation } pie_TRANSLATE(psShapeTemp->connectors[0].x, psShapeTemp->connectors[0].z, psShapeTemp->connectors[0].y); pie_MatRotY(-rot.direction); /* Draw it */ if (psMountShape) { pie_Draw3DShape(psMountShape, 0, colour, brightness, pieFlag, iPieData); } /* translate for construct mount point if cyborg */ if (cyborgDroid(psDroid) && psMountShape && psMountShape->nconnectors) { pie_TRANSLATE(psMountShape->connectors[0].x, psMountShape->connectors[0].z, psMountShape->connectors[0].y); } /* Draw it */ if (psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData); // In repair droid case only: if ((psDroid->droidType == DROID_REPAIR || psDroid->droidType == DROID_CYBORG_REPAIR) && psShape->nconnectors && psDroid->action == DACTION_DROIDREPAIR) { Spacetime st = interpolateObjectSpacetime(psDroid, graphicsTime); pie_TRANSLATE(psShape->connectors[0].x, psShape->connectors[0].z, psShape->connectors[0].y); pie_TRANSLATE(0, -20, 0); psShape = getImdFromIndex(MI_FLAME); /* Rotate for droid */ pie_MatRotY(st.rot.direction); pie_MatRotX(-st.rot.pitch); pie_MatRotZ(-st.rot.roll); //rotate Y pie_MatRotY(rot.direction); pie_MatRotY(-player.r.y); pie_MatRotX(-player.r.x); pie_Draw3DShape(psShape, getModularScaledGraphicsTime(psShape->animInterval, psShape->numFrames), 0, brightness, pie_ADDITIVE, 140); pie_MatRotX(player.r.x); pie_MatRotY(player.r.y); } } /* Pop Matrix */ pie_MatEnd(); break; } case DROID_PERSON: // no extra mounts for people break; default: ASSERT(!"invalid droid type", "Whoa! Weirdy type of droid found in drawComponentObject!!!"); break; } } /* We've also got a handle on the psShape here for the weapon which has a connector to point to muzzle flash attachment points - just grab it from psShape->connectors->[x|y|z] */ /* set default components transparent */ if (psDroid->asBits[COMP_PROPULSION] == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } psShape = (leftFirst ? getRightPropulsionIMD(psDroid) : getLeftPropulsionIMD(psDroid)); if (psShape != NULL) { pie_Draw3DShape(psShape, 0, colour, brightness, pieFlag, iPieData); } }
// this is able to handle multiple weapon graphics now // removed mountRotation,they get such stuff from psObj directly now static void displayCompObj(DROID *psDroid, BOOL bButton) { iIMDShape *psShape, *psJet, *psShapeTemp = NULL, *psMountShape; Vector3i zero = {0, 0, 0}; Vector2i screenCoords; SDWORD dummyZ, iConnector; PROPULSION_STATS *psPropStats; SDWORD frame; SDWORD pieFlag, iPieData; PIELIGHT brightness; const PIELIGHT specular = WZCOL_BLACK; UDWORD colour; UBYTE i; if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC/4 ) && psDroid->lastHitWeapon == WSC_ELECTRONIC && !gamePaused()) { colour = getPlayerColour(rand()%MAX_PLAYERS); } else { colour = getPlayerColour(psDroid->player); } /* get propulsion stats */ psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat; ASSERT_OR_RETURN( , psPropStats != NULL, "invalid propulsion stats pointer"); //set pieflag for button object or ingame object if ( bButton ) { pieFlag = pie_BUTTON; } else { pieFlag = 0; } if(!bButton) { brightness = pal_SetBrightness(psDroid->illumination); pieFlag = pie_SHADOW; } else { brightness = WZCOL_WHITE; } /* We've got a z value here _and_ screen coords of origin */ dummyZ = pie_RotateProject(&zero, &screenCoords); /* set default components transparent */ if ( psDroid->asBits[COMP_PROPULSION].nStat == 0 ) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { iPieData = 0; } if (!bButton && psPropStats->propulsionType == PROPULSION_TYPE_PROPELLOR) { // FIXME: change when adding submarines to the game pie_TRANSLATE(0, -world_coord(1)/2.3f, 0); } //uses psShapeTemp too separate it from turret's psShape psShapeTemp = (leftFirst ? getLeftPropulsionIMD(psDroid) : getRightPropulsionIMD(psDroid)); if(psShapeTemp!=NULL) { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData); } /* set default components transparent */ if ( psDroid->asBits[COMP_BODY].nStat == 0 ) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } /* Get the body graphic now*/ //uses psShapeTemp too separate it from turret's psShape psShapeTemp = BODY_IMD(psDroid,psDroid->player); if(psShapeTemp!=NULL) { // FIXME if ( psDroid->droidType == DROID_PERSON) { /* draw body if not animating */ if ( psDroid->psCurAnim == NULL || psDroid->psCurAnim->bVisible == false ) { // FIXME - hideous....!!!! pie_MatScale(.75f); pie_Draw3DShape(psShapeTemp, 0, psDroid->player-6, brightness, specular, pieFlag, iPieData); } } else if (cyborgDroid(psDroid)) { /* draw body if cyborg not animating */ if ( psDroid->psCurAnim == NULL || psDroid->psCurAnim->bVisible == false ) { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData); } } else { pie_Draw3DShape(psShapeTemp, 0, colour, brightness, specular, pieFlag, iPieData); } } /* render vtol jet if flying - horrible hack - GJ */ if (((psPropStats->propulsionType == PROPULSION_TYPE_LIFT) && //(psDroid->droidType != DROID_CYBORG)) && (!bButton)) (!cyborgDroid(psDroid))) && (!bButton)) { /* show flame if above ground */ if ( psDroid->sMove.Status != MOVEINACTIVE ) { /* draw flame if found */ /* GJ TODO: add flame-finding code here */ psJet = asBodyStats[psDroid->asBits[COMP_BODY].nStat].pFlameIMD; if ( psJet != NULL ) { pie_Draw3DShape(psJet, getModularScaledGraphicsTime(100, psJet->numFrames), colour, brightness, specular, pie_ADDITIVE, 200); } } } //don't change the screen coords of an object if drawing it in a button if (!bButton) { /* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */ calcScreenCoords(psDroid); } /* set default components transparent */ if (psDroid->asWeaps[0].nStat == 0 && psDroid->asBits[COMP_SENSOR].nStat == 0 && psDroid->asBits[COMP_ECM].nStat == 0 && psDroid->asBits[COMP_BRAIN].nStat == 0 && psDroid->asBits[COMP_REPAIRUNIT].nStat == 0 && psDroid->asBits[COMP_CONSTRUCT].nStat == 0) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } /* Indenting here is only to show new matrix context */ { psShapeTemp = BODY_IMD(psDroid,psDroid->player); if( psShapeTemp->nconnectors ) { /* vtol weapons attach to connector 2 (underneath); * all others to connector 1 */ /* VTOL's now skip the first 5 connectors(0 to 4), VTOL's use 5,6,7,8 etc now */ if ( (psPropStats->propulsionType == PROPULSION_TYPE_LIFT) && psDroid->droidType == DROID_WEAPON ) { iConnector = VTOL_CONNECTOR_START; } else { iConnector = 0; } switch(psDroid->droidType) { case DROID_DEFAULT: case DROID_TRANSPORTER: case DROID_CYBORG: case DROID_CYBORG_SUPER: case DROID_WEAPON: case DROID_COMMAND: // command droids have a weapon to store all the graphics /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ /* Double check that the weapon droid actually has any */ for (i = 0;i < psDroid->numWeaps;i++) { if (psDroid->asWeaps[i].nStat > 0 || psDroid->droidType == DROID_DEFAULT) { if ( psShapeTemp->connectors ) { Rotation rot = getInterpolatedWeaponRotation(psDroid, i, graphicsTime); pie_MatBegin(); //reset Z? dummyZ = pie_RotateProject(&zero, &screenCoords); //to skip number of VTOL_CONNECTOR_START ground unit connectors if ( iConnector < VTOL_CONNECTOR_START ) { pie_TRANSLATE(psShapeTemp->connectors[i].x, psShapeTemp->connectors[i].z, psShapeTemp->connectors[i].y); } else { pie_TRANSLATE( psShapeTemp->connectors[iConnector + i].x, psShapeTemp->connectors[iConnector + i].z, psShapeTemp->connectors[iConnector + i].y ); } pie_MatRotY(-rot.direction); /* vtol weapons inverted */ if ( iConnector >= VTOL_CONNECTOR_START ) { pie_MatRotZ(65536/2); //this might affect gun rotation } /* Get the mount graphic */ psShape = WEAPON_MOUNT_IMD(psDroid, i); pie_TRANSLATE(0,0,psDroid->asWeaps[i].recoilValue/3); /* Draw it */ if(psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData); } pie_TRANSLATE(0,0,psDroid->asWeaps[i].recoilValue); /* translate for weapon mount point */ if (psShape && psShape->nconnectors) { pie_TRANSLATE(psShape->connectors->x, psShape->connectors->z, psShape->connectors->y); } /* vtol weapons inverted */ if ( iConnector >= VTOL_CONNECTOR_START ) { //pitch the barrel down pie_MatRotX(-rot.pitch); } else { //pitch the barrel up pie_MatRotX(rot.pitch); } /* Get the weapon (gun?) graphic */ psShape = WEAPON_IMD(psDroid, i); // We have a weapon so we draw it and a muzzle flash from weapon connector if (psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData); if (psShape->nconnectors) { unsigned int connector_num = 0; // which barrel is firing if model have multiple muzzle connectors? if (psDroid->asWeaps[i].shotsFired && (psShape->nconnectors > 1)) { // shoot first, draw later - substract one shot to get correct results connector_num = (psDroid->asWeaps[i].shotsFired - 1) % (psShape->nconnectors); } /* Now we need to move to the end of the firing barrel (there maybe multiple barrels) */ pie_TRANSLATE( psShape->connectors[connector_num].x, psShape->connectors[connector_num].z, psShape->connectors[connector_num].y); //and draw the muzzle flash psShape = MUZZLE_FLASH_PIE(psDroid, i); if (psShape) { //assume no clan colours for muzzle effects if ((psShape->numFrames == 0) || (psShape->animInterval <= 0)) { //no anim so display one frame for a fixed time if (gameTime < (psDroid->asWeaps[i].lastFired + BASE_MUZZLE_FLASH_DURATION)) { pie_Draw3DShape(psShape, 0, 0, brightness, WZCOL_BLACK, pieFlag | pie_ADDITIVE, EFFECT_MUZZLE_ADDITIVE); } } else { // animated muzzle frame = (gameTime - psDroid->asWeaps[i].lastFired) / psShape->animInterval; if (frame < psShape->numFrames) { pie_Draw3DShape(psShape, frame, 0, brightness, WZCOL_BLACK, pieFlag | pie_ADDITIVE, EFFECT_MUZZLE_ADDITIVE); } } } } } } /* Pop Matrix */ pie_MatEnd(); } } break; case DROID_SENSOR: case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: case DROID_ECM: case DROID_REPAIR: case DROID_CYBORG_REPAIR: { Rotation rot = getInterpolatedWeaponRotation(psDroid, 0, graphicsTime); switch (psDroid->droidType) { default: ASSERT(false, "..."); case DROID_SENSOR: psMountShape = SENSOR_MOUNT_IMD(psDroid, psDroid->player); /* Get the sensor graphic, assuming it's there */ psShape = SENSOR_IMD(psDroid, psDroid->player); break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: psMountShape = CONSTRUCT_MOUNT_IMD(psDroid, psDroid->player); /* Get the construct graphic assuming it's there */ psShape = CONSTRUCT_IMD(psDroid, psDroid->player); break; case DROID_ECM: psMountShape = ECM_MOUNT_IMD(psDroid, psDroid->player); /* Get the ECM graphic assuming it's there.... */ psShape = ECM_IMD(psDroid, psDroid->player); break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: psMountShape = REPAIR_MOUNT_IMD(psDroid, psDroid->player); /* Get the Repair graphic assuming it's there.... */ psShape = REPAIR_IMD(psDroid, psDroid->player); break; } /* Get the mounting graphic - we've already moved to the right position Allegedly - all droids will have a mount graphic so this shouldn't fall on it's arse......*/ //sensor and cyborg and ecm uses connectors[0] pie_MatBegin(); //reset Z? dummyZ = pie_RotateProject(&zero, &screenCoords); /* vtol weapons inverted */ if ( iConnector >= VTOL_CONNECTOR_START ) { pie_MatRotZ(65536/2); //this might affect gun rotation } pie_TRANSLATE( psShapeTemp->connectors[0].x, psShapeTemp->connectors[0].z, psShapeTemp->connectors[0].y ); pie_MatRotY(-rot.direction); /* Draw it */ if (psMountShape) { pie_Draw3DShape(psMountShape, 0, colour, brightness, specular, pieFlag, iPieData); } /* translate for construct mount point if cyborg */ if (cyborgDroid(psDroid) && psMountShape && psMountShape->nconnectors) { pie_TRANSLATE(psMountShape->connectors[0].x, psMountShape->connectors[0].z, psMountShape->connectors[0].y); } /* Draw it */ if(psShape) { pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData); // In repair droid case only: if ((psDroid->droidType == DROID_REPAIR || psDroid->droidType == DROID_CYBORG_REPAIR) && psShape->nconnectors && psDroid->action == DACTION_DROIDREPAIR) { SPACETIME st = interpolateObjectSpacetime((SIMPLE_OBJECT *)psDroid, graphicsTime); Rotation rot = getInterpolatedWeaponRotation(psDroid, 0, graphicsTime); pie_TRANSLATE( psShape->connectors[0].x, psShape->connectors[0].z, psShape->connectors[0].y ); pie_TRANSLATE(0,-20,0); psShape = getImdFromIndex(MI_FLAME); /* Rotate for droid */ pie_MatRotY(st.rot.direction); pie_MatRotX(-st.rot.pitch); pie_MatRotZ(-st.rot.roll); //rotate Y pie_MatRotY(rot.direction); pie_MatRotY(-player.r.y); pie_MatRotX(-player.r.x); /* Dither on software */ pie_Draw3DShape(psShape, getModularScaledGraphicsTime(100, psShape->numFrames), 0, brightness, WZCOL_BLACK, pie_ADDITIVE, 140); /* Dither off software */ pie_MatRotX(player.r.x); pie_MatRotY(player.r.y); } } /* Pop Matrix */ pie_MatEnd(); break; } case DROID_PERSON: // no extra mounts for people break; default: ASSERT(!"invalid droid type", "Whoa! Weirdy type of droid found in drawComponentObject!!!"); break; } } /* We've also got a handle on the psShape here for the weapon which has a connector to point to muzzle flash attachment points - just grab it from psShape->connectors->[x|y|z] */ } // end of illustrative indentation - see above /* set default components transparent */ if ( psDroid->asBits[COMP_PROPULSION].nStat == 0 ) { pieFlag |= pie_TRANSLUCENT; iPieData = DEFAULT_COMPONENT_TRANSLUCENCY; } else { pieFlag &= ~pie_TRANSLUCENT; iPieData = 0; } psShape = (leftFirst ? getRightPropulsionIMD(psDroid) : getLeftPropulsionIMD(psDroid)); if(psShape!=NULL) { pie_Draw3DShape(psShape, 0, colour, brightness, specular, pieFlag, iPieData); } }
// multiple turrets display removed the pointless mountRotation void displayComponentObject(DROID *psDroid) { Vector3i position, rotation; int32_t xShift,zShift; SDWORD frame; PROPULSION_STATS *psPropStats; UDWORD tileX,tileY; MAPTILE *psTile; SPACETIME st = interpolateObjectSpacetime((SIMPLE_OBJECT *)psDroid, graphicsTime); psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat; leftFirst = angleDelta(player.r.y - st.rot.direction) <= 0; /* Push the matrix */ pie_MatBegin(); /* Get internal tile units coordinates */ xShift = map_round(player.p.x); zShift = map_round(player.p.z); /* Mask out to tile_units resolution */ pie_TRANSLATE(xShift,0,-zShift); /* Get the real position */ position.x = (st.pos.x - player.p.x) - terrainMidX*TILE_UNITS; position.z = terrainMidY*TILE_UNITS - (st.pos.y - player.p.z); position.y = st.pos.z; if(psDroid->droidType == DROID_TRANSPORTER) { position.y += bobTransporterHeight(); } /* Get all the pitch,roll,yaw info */ rotation.y = -st.rot.direction; rotation.x = st.rot.pitch; rotation.z = st.rot.roll; /* Translate origin */ pie_TRANSLATE(position.x,position.y,position.z); /* Rotate for droid */ pie_MatRotY(rotation.y); pie_MatRotX(rotation.x); pie_MatRotZ(rotation.z); if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC) && psDroid->lastHitWeapon == WSC_ELECTRONIC) { objectShimmy( (BASE_OBJECT*) psDroid ); } if (psDroid->lastHitWeapon == WSC_EMP && (gameTime - psDroid->timeLastHit < EMP_DISABLE_TIME)) { Vector3i position; //add an effect on the droid position.x = st.pos.x + DROID_EMP_SPREAD; position.y = st.pos.z + rand()%8; position.z = st.pos.y + DROID_EMP_SPREAD; effectGiveAuxVar(90+rand()%20); addEffect(&position,EFFECT_EXPLOSION,EXPLOSION_TYPE_PLASMA,false,NULL,0); } if ((psDroid->visible[selectedPlayer] == UBYTE_MAX) || demoGetStatus()) { //ingame not button object //should render 3 mounted weapons now displayCompObj(psDroid, false); } else { // make sure it's not over water. tileX = st.pos.x/TILE_UNITS; tileY = st.pos.y/TILE_UNITS; // double check it's on map if ( tileX < mapWidth && tileY < mapHeight ) { psTile = mapTile(tileX,tileY); if (terrainType(psTile) != TER_WATER) { frame = gameTime/BLIP_ANIM_DURATION + psDroid->id; //visible[selectedPlayer]; pie_Draw3DShape(getImdFromIndex(MI_BLIP), frame, 0, WZCOL_WHITE, WZCOL_BLACK, pie_ADDITIVE, psDroid->visible[selectedPlayer] / 2); /* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */ } } } pie_MatEnd(); }