Ejemplo n.º 1
0
/**
**	Move unit to oil platform.
**
**	@param unit	Pointer to unit.
**	@return		TRUE if reached, otherwise FALSE.
*/
local int MoveToOilWell(Unit* unit)
{
    Unit* well;
    int i;

    if( !(i=HandleActionMove(unit)) ) {	// reached end-point
	return 0;
    }
    DebugLevel3("Result: %d\n",i);
    if( i==-1 ) {
	DebugLevel2("OIL-WELL NOT REACHED\n");
	return -1;
    }

    well=unit->Command.Data.Move.Goal;

    if( !well ) {
        DebugLevel2("Invalid Oil Well\n");
	return -1;
    }

    // FIXME: the incomplete oil well didn't completed
    if( well->Command.Action==UnitActionBuilded ) {
        DebugLevel2("Invalid Oil Well\n");
	return -1;
    }

    unit->Command.Action=UnitActionHaulOil;

    DebugCheck( !well || MapDistanceToUnit(unit->X,unit->Y,well)!=1 );

    //
    // Activate oil-well
    //
    if( !well->Type->GivesOil ) {
	// OilWell destoryed.
	DebugLevel3("WAIT after oil-well destroyed %d\n",unit->Wait);
	unit->Command.Action=UnitActionStill;
	unit->SubAction=0;
	return 0;
    }
    well->Command.Data.OilWell.Active++;
    DebugLevel0(__FUNCTION__": +%d\n",well->Command.Data.OilWell.Active);
    well->Frame=2;			// FIXME: this should be hard coded!

    RemoveUnit(unit);
    unit->X=well->X;
    unit->Y=well->Y;

    if( HAUL_FOR_OIL<UNIT_MAX_WAIT ) {
	unit->Wait=HAUL_FOR_OIL;
    } else {
	unit->Wait=UNIT_MAX_WAIT;
    }
    unit->Value=HAUL_FOR_OIL-unit->Wait;

    return 1;
}
Ejemplo 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;
}
Ejemplo n.º 3
0
/*
**	Return with the wood.
**	Return TRUE if reached, otherwise FALSE.
*/
local int ReturnWithWood(Unit* unit)
{
    int x;
    int y;
    //int dx;
    //int dy;
    Unit* destu;

    if( !HandleActionMove(unit) ) {	// reached end-point
	return 0;
    }

    DebugCheck( unit->Wait!=1 );

#if 0
    // reached nearly? and is there an wood deposit?

    x=unit->Command.Data.Move.DX;
    y=unit->Command.Data.Move.DY;
    dx=unit->X-x;
    dy=unit->Y-y;
    destu=WoodDepositOnMap(x,y);

    DebugLevel3("Near unit %d,%d =%Zd\n",x,y,destu-UnitsPool);

    if( !destu || dx<-1 || dx>destu->Type->TileWidth
	    || dy<-1 || dy>destu->Type->TileHeight ) {
      	DebugLevel2("WOOD-DEPOSIT NOT REACHED %d=%d,%Zd\n"
		    ,destu-UnitsPool,dx,dy);
	unit->Command.Action=UnitActionStill;
	unit->SubAction=0;
	return 0;
    }
#endif
    x=unit->Command.Data.Move.DX;
    y=unit->Command.Data.Move.DY;
    destu=WoodDepositOnMap(x,y);
    if( !destu || MapDistanceToUnit(unit->X,unit->Y,destu)!=1 ) {
      DebugLevel2("WOOD-DEPOSIT NOT REACHED %Zd=%d,%d ? %d\n"
		  ,destu-UnitsPool,x,y
		  ,MapDistanceToUnit(unit->X,unit->Y,destu));
	unit->Command.Action=UnitActionStill;
	unit->SubAction=0;
	return 0;
    }

    unit->Command.Action=UnitActionHarvest;

    RemoveUnit(unit);
    unit->X=destu->X;
    unit->Y=destu->Y;

    //
    //	Update wood.
    //
    unit->Player->Wood+=unit->Player->WoodPerChop;
    if( unit->Player==ThisPlayer ) {
	MustRedraw|=RedrawResources;
    }

    if( unit->Type->Type==UnitPeonWithWood ) {
	unit->Type=&UnitTypes[UnitPeon];
    } else if( unit->Type->Type==UnitPeasantWithWood ) {
	unit->Type=&UnitTypes[UnitPeasant];
    } else {
	DebugLevel0("Wrong unit for returning wood %d\n"
	    ,unit->Type->Type);
    }

    if( WAIT_FOR_WOOD<UNIT_MAX_WAIT ) {
	unit->Wait=WAIT_FOR_WOOD;
    } else {
	unit->Wait=UNIT_MAX_WAIT;
    }
    unit->Value=WAIT_FOR_WOOD-unit->Wait;
    
    return 1;
}
Ejemplo n.º 4
0
/**
**	Unit Demolishs
**
**	@param unit	Unit, for that the demolish is handled.
*/
global void HandleActionDemolish(Unit* unit)
{
    Unit* table[MAX_UNITS];
    int i;
    int n;
    int x, y, ix, iy;
    Unit* goal;
    int err;

    DebugLevel3("Demolish %d\n",unit-Units);

    switch( unit->SubAction ) {
	//
	//	Move near to target.
	//
	case 0:
	    // FIXME: RESET FIRST!!
	    err=HandleActionMove(unit); 
	    if( unit->Reset ) {
		goal=unit->Command.Data.Move.Goal;

		//
		//	Target is dead, stop demolish
		//
		if( goal && (!goal->Type || !goal->HP
			|| goal->Command.Action==UnitActionDie) ) {
		    // FIXME: this can't happen, HandleActionMove resets goal!
		    unit->Command.Data.Move.Goal=NoUnitP;
		    unit->Command.Action=UnitActionStill;
		    return;
		}

		//
		//	Have reached target?
		//
		if( goal ) {
		    if( MapDistanceToUnit(unit->X,unit->Y,goal)<=1 ) {
			unit->State=0;
			unit->SubAction=1;
		    }
		} else if( MapDistance(unit->X,unit->Y
			,unit->Command.Data.Move.DX
			,unit->Command.Data.Move.DY)<=1 ) {
		    unit->State=0;
		    unit->SubAction=1;
		} else if( err ) {
		    return;
		}
		unit->Command.Action=UnitActionDemolish;
	    }
	    break;

	//
	//	Demolish the target.
	//
	case 1:
            x=unit->X;
            y=unit->Y;
            DestroyUnit(unit);
	    // FIXME: Must play explosion sound
            n=SelectUnits(x-2,y-2, x+2, y+2,table);
	    // FIXME: Don't hit flying units!
            for( i=0; i<n; ++i ) {
                HitUnit(table[i],DEMOLISH_DAMAGE);
            }

            for( ix=x-2; ix<=x+2; ix++ ) {
		for( iy=y-2; iy<=y+2; 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);
		    }
		}
	    }
	    break;
    }
}
Ejemplo n.º 5
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;
    }
}
Ejemplo n.º 6
0
/**
**  Work for missile hit.
**
**  @param missile  Missile reaching end-point.
*/
void MissileHit(Missile *missile)
{
	CUnit *goal;
	int x;
	int y;
	CUnit *table[UnitMax];
	int n;
	int i;
	int splash;

	if (missile->Type->ImpactSound.Sound) {
		PlayMissileSound(missile, missile->Type->ImpactSound.Sound);
	}

	x = missile->X + missile->Type->Width / 2;
	y = missile->Y + missile->Type->Height / 2;

	//
	// The impact generates a new missile.
	//
	if (missile->Type->ImpactMissile) {
		MakeMissile(missile->Type->ImpactMissile, x, y, x, y);
	}
	if (missile->Type->ImpactParticle) {
		missile->Type->ImpactParticle->pushPreamble();
		missile->Type->ImpactParticle->pushInteger(x);
		missile->Type->ImpactParticle->pushInteger(y);
		missile->Type->ImpactParticle->run();
	}

	if (!missile->SourceUnit) {  // no owner - green-cross ...
		return;
	}

	x /= TileSizeX;
	y /= TileSizeY;

	if (x < 0 || y < 0 || x >= Map.Info.MapWidth || y >= Map.Info.MapHeight) {
		// FIXME: this should handled by caller?
		DebugPrint("Missile gone outside of map!\n");
		return;  // outside the map.
	}

	//
	// Choose correct goal.
	//
	if (!missile->Type->Range) {
		if (missile->TargetUnit) {
			//
			// Missiles without range only hits the goal always.
			//
			goal = missile->TargetUnit;
			if (goal->Destroyed) {  // Destroyed
				goal->RefsDecrease();
				missile->TargetUnit = NoUnitP;
				return;
			}
			MissileHitsGoal(missile, goal, 1);
			return;
		}
		return;
	}

	//
	// Hits all units in range.
	//
	i = missile->Type->Range;
	n = UnitCache.Select(x - i + 1, y - i + 1, x + i, y + i, table, UnitMax);
	Assert(missile->SourceUnit != NULL);
	for (i = 0; i < n; ++i) {
		goal = table[i];
		//
		// Can the unit attack the this unit-type?
		// NOTE: perhaps this should be come a property of the missile.
		//
		if (CanTarget(missile->SourceUnit->Type, goal->Type)) {
			splash = MapDistanceToUnit(x, y, goal);
			if (splash) {
				splash *= missile->Type->SplashFactor;
			} else {
				splash = 1;
			}
			MissileHitsGoal(missile, goal, splash);
		}
	}
}