예제 #1
0
/**
**	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");
}
예제 #2
0
/**
**	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);
    }
예제 #4
0
/**
**	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");
	    }
	);
예제 #5
0
/**
**	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;
    }
}
예제 #6
0
/**
**	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);
}
예제 #7
0
/**
**	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;
    }
}