예제 #1
0
/* virtual */ void COrder_Still::Execute(CUnit &unit)
{
	// If unit is not bunkered and removed, wait
	if (unit.Removed
		//Wyrmgus start
//		&& (unit.Container == nullptr || unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value == false)) {
		&& (unit.Container == nullptr || !unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value || !unit.Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value)) { // make both the unit and the transporter have the tag be necessary for the attack to be possible
			if (unit.Container != nullptr) {
				LeaveShelter(unit); // leave shelter if surrounded
			}
		//Wyrmgus end
		return ;
	}
	this->Finished = false;

	switch (this->State) {
		case SUB_STILL_STANDBY:
			//Wyrmgus start
//			UnitShowAnimation(unit, unit.Type->Animations->Still);
			if (unit.Variable[STUN_INDEX].Value == 0) { //only show the idle animation when still if the unit is not stunned
				UnitShowAnimation(unit, unit.GetAnimations()->Still);
			}
			if (SyncRand(100000) == 0) {
				PlayUnitSound(unit, VoiceIdle);
			}
			unit.StepCount = 0;
			//Wyrmgus end
			break;
		case SUB_STILL_ATTACK: // attacking unit in attack range.
			AnimateActionAttack(unit, *this);
			break;
	}
	if (unit.Anim.Unbreakable) { // animation can't be aborted here
		return;
	}
	//Wyrmgus start
	if (unit.Variable[STUN_INDEX].Value > 0) { //if unit is stunned, remain still
		return;
	}
	//Wyrmgus end
	this->State = SUB_STILL_STANDBY;
	this->Finished = (this->Action == UnitActionStill);
	if (this->Action == UnitActionStandGround || unit.Removed || unit.CanMove() == false) {
		if (unit.AutoCastSpell) {
			this->AutoCastStand(unit);
		}
		if (unit.IsAgressive()) {
			this->AutoAttackStand(unit);
		}
	} else {
		if (AutoCast(unit) || (unit.IsAgressive() && AutoAttack(unit))
			|| AutoRepair(unit)
			//Wyrmgus start
//			|| MoveRandomly(unit)) {
			|| MoveRandomly(unit) || PickUpItem(unit)) {
			//Wyrmgus end
		}
	}
}
예제 #2
0
/* virtual */ void COrder_Still::Execute(CUnit &unit)
{
	// If unit is not bunkered and removed, wait
	if (unit.Removed
		&& (unit.Container == NULL || unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value == false)) {
		return ;
	}
	this->Finished = false;

	switch (this->State) {
		case SUB_STILL_STANDBY:
			UnitShowAnimation(unit, unit.Type->Animations->Still);
			break;
		case SUB_STILL_ATTACK: // attacking unit in attack range.
			AnimateActionAttack(unit, *this);
			break;
	}
	if (unit.Anim.Unbreakable) { // animation can't be aborted here
		return;
	}
	this->State = SUB_STILL_STANDBY;
	this->Finished = (this->Action == UnitActionStill);
	if (this->Action == UnitActionStandGround || unit.Removed || unit.CanMove() == false) {
		if (unit.AutoCastSpell) {
			this->AutoCastStand(unit);
		}
		if (unit.IsAgressive()) {
			this->AutoAttackStand(unit);
		}
	} else {
		if (AutoCast(unit) || (unit.IsAgressive() && AutoAttack(unit))
			|| AutoRepair(unit)
			|| MoveRandomly(unit)) {
		}
	}
}
예제 #3
0
/**
**  Save the state of a unit to file.
**
**  @param unit  Unit pointer to be saved.
**  @param file  Output file.
*/
void SaveUnit(const CUnit &unit, CFile *file)
{
	CUnit *uins;
	int i;

	file->printf("\nUnit(%d, ", UnitNumber(unit));

	// 'type and 'player must be first, needed to create the unit slot
	file->printf("\"type\", \"%s\", ", unit.Type->Ident.c_str());
	if (unit.Seen.Type) {
		file->printf("\"seen-type\", \"%s\", ", unit.Seen.Type->Ident.c_str());
	}

	file->printf("\"player\", %d,\n  ", unit.Player->Index);

	if (unit.Next) {
		file->printf("\"next\", %d, ", UnitNumber(*unit.Next));
	}

	file->printf("\"tile\", {%d, %d}, ", unit.tilePos.x, unit.tilePos.y);
	file->printf("\"refs\", %d, ", unit.Refs);
#if 0
	// latimerius: why is this so complex?
	// JOHNS: An unit can be owned by a new player and have still the old stats
	for (i = 0; i < PlayerMax; ++i) {
		if (&unit.Type->Stats[i] == unit.Stats) {
			file->printf("\"stats\", %d,\n  ", i);
			break;
		}
	}
	// latimerius: what's the point of storing a pointer value anyway?
	if (i == PlayerMax) {
		file->printf("\"stats\", \"S%08X\",\n  ", (int)unit.Stats);
	}
#else
	file->printf("\"stats\", %d,\n  ", unit.Player->Index);
#endif
	file->printf("\"pixel\", {%d, %d}, ", unit.IX, unit.IY);
	file->printf("\"seen-pixel\", {%d, %d}, ", unit.Seen.IX, unit.Seen.IY);
	file->printf("\"frame\", %d, ", unit.Frame);
	if (unit.Seen.Frame != UnitNotSeen) {
		file->printf("\"seen\", %d, ", unit.Seen.Frame);
	} else {
		file->printf("\"not-seen\", ");
	}
	file->printf("\"direction\", %d,\n  ", unit.Direction);
	file->printf("\"attacked\", %lu,\n ", unit.Attacked);
	file->printf(" \"current-sight-range\", %d,", unit.CurrentSightRange);
	if (unit.Burning) {
		file->printf(" \"burning\",");
	}
	if (unit.Destroyed) {
		file->printf(" \"destroyed\",");
	}
	if (unit.Removed) {
		file->printf(" \"removed\",");
	}
	if (unit.Selected) {
		file->printf(" \"selected\",");
	}
	if (unit.RescuedFrom) {
		file->printf(" \"rescued-from\", %d,", unit.RescuedFrom->Index);
	}
	// n0b0dy: How is this useful?
	// mr-russ: You can't always load units in order, it saved the information
	// so you can load a unit whose Container hasn't been loaded yet.
	// SEE unit loading code.
	if (unit.Container && unit.Removed) {
		file->printf(" \"host-info\", {%d, %d, %d, %d}, ",
			unit.Container->tilePos.x, unit.Container->tilePos.y,
			unit.Container->Type->TileWidth,
			unit.Container->Type->TileHeight);
	}
	file->printf(" \"seen-by-player\", \"");
	for (i = 0; i < PlayerMax; ++i) {
		file->printf("%c", (unit.Seen.ByPlayer & (1 << i)) ? 'X' : '_');
	}
	file->printf("\",\n ");
	file->printf(" \"seen-destroyed\", \"");
	for (i = 0; i < PlayerMax; ++i) {
		file->printf("%c", (unit.Seen.Destroyed & (1 << i)) ? 'X' : '_');
	}
	file->printf("\",\n ");
	if (unit.Constructed) {
		file->printf(" \"constructed\",");
	}
	if (unit.Seen.Constructed) {
		file->printf(" \"seen-constructed\",");
	}
	file->printf(" \"seen-state\", %d, ", unit.Seen.State);
	if (unit.Active) {
		file->printf(" \"active\",");
	}
	file->printf("\"ttl\", %lu, ", unit.TTL);

	for (i = 0; i < (int)UnitTypeVar.GetNumberVariable(); ++i) {
			file->printf("\"%s\", {Value = %d, Max = %d, Increase = %d, Enable = %s},\n  ",
				UnitTypeVar.VariableNameLookup[i], unit.Variable[i].Value, unit.Variable[i].Max,
				unit.Variable[i].Increase, unit.Variable[i].Enable ? "true" : "false");
	}

	file->printf("\"group-id\", %d,\n  ", unit.GroupId);
	file->printf("\"last-group\", %d,\n  ", unit.LastGroup);

	file->printf("\"resources-held\", %d,\n  ", unit.ResourcesHeld);
	if (unit.CurrentResource) {
		file->printf("\"current-resource\", \"%s\",\n  ",
			DefaultResourceNames[unit.CurrentResource].c_str());
	}
	if (unit.SubAction && unit.IsAgressive() &&
		(unit.CurrentAction() == UnitActionStill ||
		unit.CurrentAction() == UnitActionStandGround))
	{
		//Force recalculate Guard points
		//if unit atack from StandGround then attac target is recalculate
		//When unit first time handle action code.
		file->printf("\"sub-action\", 0, ");
	} else	{
		file->printf("\"sub-action\", %d, ", unit.SubAction);
	}
	file->printf("\"wait\", %d, ", unit.Wait);
	file->printf("\"state\", %d,", unit.State);
	file->printf("\"anim-wait\", %d,", unit.Anim.Wait);
	for (i = 0; i < NumAnimations; ++i) {
		if (AnimationsArray[i] == unit.Anim.CurrAnim) {
			file->printf("\"curr-anim\", %d,", i);
			file->printf("\"anim\", %d,", unit.Anim.Anim - unit.Anim.CurrAnim);
			break;
		}
	}
	if (unit.Anim.Unbreakable) {
		file->printf(" \"unbreakable\",");
	}
	file->printf("\n  \"blink\", %d,", unit.Blink);
	if (unit.Moving) {
		file->printf(" \"moving\",");
	}
	if (unit.ReCast) {
		file->printf(" \"re-cast\",");
	}
	if (unit.Boarded) {
		file->printf(" \"boarded\",");
	}
	if (unit.AutoRepair) {
		file->printf(" \"auto-repair\",");
	}

	if (unit.NextWorker) {
		if (unit.NextWorker->Destroyed) {
			/* this unit is destroyed so it's not in the global unit
			 * array - this means it won't be saved!!! */
			printf ("FIXME: storing destroyed Worker - loading will fail.\n");
		}
		file->printf(" \"next-worker\", \"%s\",",
			UnitReference(*unit.NextWorker).c_str());
	}

	file->printf(" \"units-boarded-count\", %d,", unit.BoardCount);

	if (unit.UnitInside) {
		file->printf("\n  \"units-contained\", {");
		uins = unit.UnitInside->PrevContained;
		for (i = unit.InsideCount; i; --i, uins = uins->PrevContained) {
			file->printf("\"%s\"", UnitReference(*uins).c_str());
			if (i > 1) {
				file->printf(", ");
			}
		}
		file->printf("},\n  ");
	}
	Assert((unsigned int)unit.OrderCount == unit.Orders.size());
	file->printf("\"order-count\", %d,\n  ", unit.OrderCount);
	file->printf("\"order-flush\", %d,\n  ", unit.OrderFlush);
	file->printf("\"orders\", {");
	for (i = 0; i < unit.OrderCount; ++i) {
		file->printf("\n ");
		SaveOrder(unit.Orders[i], file);
		if (i < unit.OrderCount - 1) {
			file->printf(",");
		}
	}
	file->printf("},\n  \"saved-order\", ");
	SaveOrder((COrderPtr)(&unit.SavedOrder), file);
	file->printf(",\n  \"critical-order\", ");
	SaveOrder((COrderPtr)(&unit.CriticalOrder), file);
	file->printf(",\n  \"new-order\", ");
	SaveOrder((COrderPtr)(&unit.NewOrder), file);

	//
	//  Order data part
	//
	switch (unit.CurrentAction()) {
		case UnitActionStill:
			// FIXME: support other resource types
			if (unit.Type->GivesResource) {
				file->printf(", \"resource-active\", %d", unit.Data.Resource.Active);
				if (unit.Type->CanHarvest) {
					file->printf(", \"data-resource\", {\"assigned\", %d", unit.Data.Resource.Assigned);
					if (unit.Data.Resource.Workers) {
						if (unit.Data.Resource.Workers->Destroyed) {
							/* this unit is destroyed so it's not in the global unit
							* array - this means it won't be saved!!! */
							printf ("FIXME: storing destroyed Worker - loading will fail.\n");
						}
						file->printf(", \"first-worker\", \"%s\"",
							UnitReference(*unit.Data.Resource.Workers).c_str());
					}
					file->printf("}");
				}
			}
			break;
		case UnitActionResource:
			file->printf(", \"data-res-worker\", {\"time-to-harvest\", %d", unit.Data.ResWorker.TimeToHarvest);
			if (unit.Data.ResWorker.DoneHarvesting) {
				file->printf(", \"done-harvesting\"");
			}
			file->printf("}");
			break;
		case UnitActionBuilt:
			{
				CConstructionFrame *cframe;
				int frame;

				cframe = unit.Type->Construction->Frames;
				frame = 0;
				while (cframe != unit.Data.Built.Frame) {
					cframe = cframe->Next;
					++frame;
				}
				file->printf(",\n  \"data-built\", {");

				if (unit.Data.Built.Worker) {
					file->printf("\"worker\", \"%s\", ",
						UnitReference(*unit.Data.Built.Worker).c_str());
				}
				file->printf("\"progress\", %d, \"frame\", %d",
					unit.Data.Built.Progress, frame);
				if (unit.Data.Built.Cancel) {
					file->printf(", \"cancel\"");
				}
				file->printf("}");
				break;
			}
		case UnitActionResearch:
			file->printf(",\n  \"data-research\", {");
			file->printf("\"ident\", \"%s\"", unit.Data.Research.Upgrade->Ident.c_str());
			file->printf("}");
			break;
		case UnitActionUpgradeTo:
			file->printf(",\n  \"data-upgrade-to\", {");
			file->printf("\"ticks\", %d", unit.Data.UpgradeTo.Ticks);
			file->printf("}");
			break;
		case UnitActionTrain:
			file->printf(",\n  \"data-train\", {");
			file->printf("\"ticks\", %d ", unit.Data.Train.Ticks);
			file->printf("}");
			break;
		default:
			file->printf(",\n  \"data-move\", {");
			if (unit.Data.Move.Cycles) {
				file->printf("\"cycles\", %d,", unit.Data.Move.Cycles);
			}
			if (unit.Data.Move.Fast) {
				file->printf("\"fast\", ");
			}
			if (unit.Data.Move.Length > 0) {
				file->printf("\"path\", {");
				for (i = 0; i < unit.Data.Move.Length; ++i) {
					file->printf("%d, ", unit.Data.Move.Path[i]);
				}
				file->printf("}");
			}
			file->printf("}");
			break;
	}

	if (unit.Goal) {
		file->printf(",\n  \"goal\", %d", UnitNumber(*unit.Goal));
	}
	if (unit.AutoCastSpell) {
		for (i = 0; (unsigned int) i < SpellTypeTable.size(); ++i) {
			if (unit.AutoCastSpell[i]) {
				file->printf(",\n  \"auto-cast\", \"%s\"", SpellTypeTable[i]->Ident.c_str());
			}
		}
	}

	file->printf(")\n");
}