/** ** Enter the transporter. ** ** @param unit Pointer to unit. */ local void EnterTransporter(Unit* unit) { Unit* transporter; int i; unit->Wait=1; unit->Orders[0].Action=UnitActionStill; unit->SubAction=0; transporter=unit->Orders[0].Goal; if( transporter->Destroyed ) { DebugLevel0Fn("Destroyed transporter\n"); RefsDebugCheck( !transporter->Refs ); if( !--transporter->Refs ) { ReleaseUnit(transporter); } unit->Orders[0].Goal=NoUnitP; return; } else if( transporter->Removed || !transporter->HP || transporter->Orders[0].Action==UnitActionDie ) { DebugLevel0Fn("Unuseable transporter\n"); RefsDebugCheck( !transporter->Refs ); --transporter->Refs; RefsDebugCheck( !transporter->Refs ); unit->Orders[0].Goal=NoUnitP; return; } RefsDebugCheck( !transporter->Refs ); --transporter->Refs; RefsDebugCheck( !transporter->Refs ); unit->Orders[0].Goal=NoUnitP; // // Find free slot in transporter. // for( i=0; i<(int)(sizeof(unit->OnBoard)/sizeof(*unit->OnBoard)); ++i ) { if( transporter->OnBoard[i]==NoUnitP ) { transporter->OnBoard[i]=unit; // FIXME: reference counts? transporter->Value++; RemoveUnit(unit,transporter); if( IsOnlySelected(transporter) ) { UpdateButtonPanel(); MustRedraw|=RedrawPanels; } return; } } DebugLevel0Fn("No free slot in transporter\n"); }
/** ** Wait for transporter. ** ** @param unit Pointer to unit. ** @return True if ship arrived/present, False otherwise. */ local int WaitForTransporter(Unit* unit) { Unit* trans; unit->Wait=6; unit->Reset=1; trans=unit->Orders[0].Goal; if( !trans || !trans->Type->Transporter ) { // FIXME: destination destroyed?? DebugLevel2Fn("TRANSPORTER NOT REACHED %d,%d\n" _C_ unit->X _C_ unit->Y); return 0; } if( trans->Destroyed ) { DebugLevel0Fn("Destroyed transporter\n"); RefsDebugCheck( !trans->Refs ); if( !--trans->Refs ) { ReleaseUnit(trans); } unit->Orders[0].Goal=NoUnitP; return 0; } else if( trans->Removed || !trans->HP || trans->Orders[0].Action==UnitActionDie ) { DebugLevel0Fn("Unusable transporter\n"); RefsDebugCheck( !trans->Refs ); --trans->Refs; RefsDebugCheck( !trans->Refs ); unit->Orders[0].Goal=NoUnitP; return 0; } if( MapDistanceToUnit(unit->X,unit->Y,trans)==1 ) { DebugLevel3Fn("Enter transporter\n"); return 1; } // // FIXME: any enemies in range attack them, while waiting. // DebugLevel2Fn("TRANSPORTER NOT REACHED %d,%d\n" _C_ unit->X _C_ unit->Y); return 0; }
void TextureManager::UnuseTexture(GLuint nTextureID) { // get map entry auto iter = m_pImpl->m_mTextureInUse.find(nTextureID); // assert that the iterator is valid (else, the texture nTextureID was not used!) assert (iter != m_pImpl->m_mTextureInUse.end()); // get the used texture unit GLuint nUsedUnit = iter->second; // remove entry in map m_pImpl->m_mTextureInUse.erase(iter); // release texture unit ReleaseUnit(nUsedUnit); }
/** ** Unit dies! ** ** @param unit The unit which dies. */ global void HandleActionDie(Unit* unit) { // // Show death animation // if( unit->Type->Animations && unit->Type->Animations->Die ) { UnitShowAnimation(unit,unit->Type->Animations->Die); } else { // some units has no death animation unit->Reset=unit->Wait=1; } // // Die sequence terminated, generate corpse. // if( unit->Reset ) { DebugLevel3("Die complete %d\n" _C_ UnitNumber(unit)); if( !unit->Type->CorpseType ) { UnitMarkSeen(unit); ReleaseUnit(unit); return; } #ifdef NEW_FOW //Fixes sight from death MapUnmarkSight(unit->Player,unit->X,unit->Y,unit->CurrentSightRange); //unit->CurrentSightRange=unit->Type->Stats->SightRange; #endif unit->State=unit->Type->CorpseScript; unit->Type=unit->Type->CorpseType; CommandStopUnit(unit); // This clears all order queues IfDebug( if( unit->Orders[0].Action!=UnitActionDie ) { DebugLevel0Fn("Reset to die is really needed\n"); } );
/** ** The unit boards a transporter. ** ** @todo FIXME: the transporter must drive to the meating point. ** While waiting for the transporter the units must defend ** themselfs. ** ** @param unit Pointer to unit. */ global void HandleActionBoard(Unit* unit) { int i; Unit* goal; DebugLevel3Fn("%p(%d) SubAction %d\n" _C_ unit _C_ UnitNumber(unit) _C_ unit->SubAction); switch( unit->SubAction ) { // // Wait for transporter // case 201: // FIXME: show still animations DebugLevel3Fn("Waiting\n"); if( WaitForTransporter(unit) ) { unit->SubAction=202; } break; // // Enter transporter // case 202: EnterTransporter(unit); break; // // Move to transporter // case 0: NewResetPath(unit); unit->SubAction=1; // FALL THROUGH default: if( unit->SubAction<=200 ) { // FIXME: if near transporter wait for enter if( (i=MoveToTransporter(unit)) ) { if( i==PF_UNREACHABLE ) { if( ++unit->SubAction==200 ) { unit->Orders[0].Action=UnitActionStill; if( (goal=unit->Orders[0].Goal) ) { RefsDebugCheck(!goal->Refs); if( !--goal->Refs ) { RefsDebugCheck(!goal->Destroyed); if( goal->Destroyed ) { ReleaseUnit(goal); } } unit->Orders[0].Goal=NoUnitP; } unit->SubAction=0; } else { unit->Wait=unit->SubAction; } } else if( i==PF_REACHED ) { unit->SubAction=201; } } } break; } }
/** ** Ai clean units in a force. ** ** @param force Force number. */ local void AiCleanForce(int force) { AiUnit** prev; AiUnit* aiunit; const AiUnitType* aitype; int counter[UnitTypeMax]; // // Release all killed units. // prev=&AiPlayer->Force[force].Units; while( (aiunit=*prev) ) { if( aiunit->Unit->Destroyed ) { RefsDebugCheck( !aiunit->Unit->Refs ); if( !--aiunit->Unit->Refs ) { ReleaseUnit(aiunit->Unit); } *prev=aiunit->Next; free(aiunit); continue; } else if( !aiunit->Unit->HP || aiunit->Unit->Orders[0].Action==UnitActionDie ) { RefsDebugCheck( !aiunit->Unit->Refs ); --aiunit->Unit->Refs; RefsDebugCheck( !aiunit->Unit->Refs ); *prev=aiunit->Next; free(aiunit); continue; } prev=&aiunit->Next; } // // Count units in force. // memset(counter,0,sizeof(counter)); aiunit=AiPlayer->Force[force].Units; while( aiunit ) { // FIXME: Should I use equivalent unit types? counter[aiunit->Unit->Type->Type]++; aiunit=aiunit->Next; } // // Look if the force is complete. // AiPlayer->Force[force].Completed=1; aitype=AiPlayer->Force[force].UnitTypes; while( aitype ) { if( aitype->Want>counter[aitype->Type->Type] ) { DebugLevel3Fn("%d: missing %s.\n" _C_ force _C_ aitype->Type->Ident); AiPlayer->Force[force].Completed=0; } counter[aitype->Type->Type]-=aitype->Want; aitype=aitype->Next; } // // Release units too much in force. // if( !AiPlayer->Force[force].Attacking ) { prev=&AiPlayer->Force[force].Units; while( (aiunit=*prev) ) { if( counter[aiunit->Unit->Type->Type]>0 ) { DebugLevel0Fn("Release unit %s\n" _C_ aiunit->Unit->Type->Ident); counter[aiunit->Unit->Type->Type]--; RefsDebugCheck( !aiunit->Unit->Refs ); --aiunit->Unit->Refs; RefsDebugCheck( !aiunit->Unit->Refs ); *prev=aiunit->Next; free(aiunit); continue; } prev=&aiunit->Next; } } DebugLevel3Fn("%d complete %d\n" _C_ force _C_ AiPlayer->Force[force].Completed); }
/** ** Unit Demolishs ** ** @param unit Unit, for that the demolish is handled. */ global void HandleActionDemolish(Unit* unit) { Unit* table[UnitMax]; int i; int n; int xmin, ymin, xmax, ymax; int ix, iy; Unit* goal; int err; DebugLevel3Fn("Demolish %d\n" _C_ UnitNumber(unit)); switch( unit->SubAction ) { // // Move near to target. // case 0: // first entry. NewResetPath(unit); unit->SubAction=1; // FALL THROUGH case 1: // FIXME: reset first!! why? (johns) err=DoActionMove(unit); if( unit->Reset ) { goal=unit->Orders[0].Goal; // // Target is dead, stop demolish. // FIXME: what should I do, go back or explode on place? // if( goal ) { if( goal->Destroyed ) { DebugLevel0Fn("Destroyed unit\n"); RefsDebugCheck( !goal->Refs ); if( !--goal->Refs ) { ReleaseUnit(goal); } // FIXME: perhaps I should choose an alternative unit->Orders[0].Goal=NoUnitP; unit->Orders[0].Action=UnitActionStill; unit->SubAction=0; return; } else if( goal->Removed || !goal->HP || goal->Orders[0].Action==UnitActionDie ) { RefsDebugCheck( !goal->Refs ); --goal->Refs; RefsDebugCheck( !goal->Refs ); unit->Orders[0].Goal=NoUnitP; // FIXME: perhaps I should choose an alternative unit->Orders[0].Action=UnitActionStill; unit->SubAction=0; return; } } // // Have reached target? FIXME: could use pathfinder result? // if( goal ) { if( MapDistanceToUnit(unit->X,unit->Y,goal)<=1 ) { unit->State=0; unit->SubAction=2; } } else if( MapDistance(unit->X,unit->Y ,unit->Orders[0].X,unit->Orders[0].Y)<=1 ) { unit->State=0; unit->SubAction=2; } else if( err==PF_UNREACHABLE ) { unit->Orders[0].Action=UnitActionStill; return; } DebugCheck( unit->Orders[0].Action!=UnitActionDemolish ); } break; // // Demolish the target. // case 2: goal=unit->Orders[0].Goal; if( goal ) { RefsDebugCheck( !goal->Refs ); --goal->Refs; RefsDebugCheck( !goal->Refs ); unit->Orders[0].Goal=NoUnitP; } xmin = unit->X - 2; ymin = unit->Y - 2; xmax = unit->X + 2; ymax = unit->Y + 2; if (xmin<0) xmin=0; if (xmax > TheMap.Width-1) xmax = TheMap.Width-1; if (ymin<0) ymin=0; if (ymax > TheMap.Height-1) ymax = TheMap.Height-1; // FIXME: Must play explosion sound // FIXME: Currently we take the X fields, the original only the O // XXXXX ..O.. // XXXXX .OOO. // XX.XX OO.OO // XXXXX .OOO. // XXXXX ..O.. // // // Effect of the explosion on units. // n=SelectUnits(xmin,ymin, xmax, ymax,table); for( i=0; i<n; ++i ) { if( table[i]->Type->UnitType!=UnitTypeFly && table[i]->HP && table[i] != unit ) { // Don't hit flying units! HitUnit(unit,table[i],DEMOLISH_DAMAGE); } } // // Terrain effect of the explosion // for( ix=xmin; ix<=xmax; ix++ ) { for( iy=ymin; iy<=ymax; iy++ ) { n=TheMap.Fields[ix+iy*TheMap.Width].Flags; if( n&MapFieldWall ) { MapRemoveWall(ix,iy); } else if( n&MapFieldRocks ) { MapRemoveRock(ix,iy); } else if( n&MapFieldForest ) { MapRemoveWood(ix,iy); } } } LetUnitDie(unit); #ifdef HIERARCHIC_PATHFINDER PfHierMapChangedCallback (xmin, ymin, xmax, ymax); #endif break; } }