 |
|  |
 |
|
E
|
 |
July 24,2005 Ctp2 Tiles in sig!
May 1999 time: 21:22
|
|
I found this in: ctp2_code\gs\gameobj\unitdata.cpp
code:
sint32 UnitData::CanBombard(CellUnitList &defender) const
{
const UnitRecord *rec = g_theUnitDB->Get(m_type);
double r = rec->GetBombardRange() + 0.5;
double rsq = r * r;
MapPoint dpos;
defender.GetPos(dpos);
if(GetDistance(dpos, m_pos, (sint32)r) > rsq)
return FALSE;
if (rec->GetCanBombardLand())
if (defender.IsAtLeastOneMoveLand())
return TRUE;
if (rec->GetCanBombardWater())
if (defender.IsAtLeastOneMoveWater() || defender.IsAtLeastOneMoveShallowWater())
return TRUE;
if (rec->GetCanBombardAir())
if (defender.IsAtLeastOneMoveAir())
return TRUE;
if (rec->GetCanBombardSpace())
if (defender.IsAtLeastOneMoveSpace())
return TRUE;
if (rec->GetCanBombardMountain())
if (defender.IsAtLeastOneMoveMountain())
return TRUE;
return FALSE;
}
sint32 UnitData::CanCounterBombard(CellUnitList &defender) const
{
if (g_theUnitDB->Get(m_type)->GetCanCounterBombard()) {
return CanBombard(defender);
} else {
return FALSE;
}
}
sint32 UnitData::CanActivelyDefend(CellUnitList &attacker) const
{
const UnitRecord *rec = g_theUnitDB->Get(m_type);
if(rec->GetActiveDefenseRange() <= 0)
return 0;
BOOL movesMatch = FALSE;
if(attacker.IsAtLeastOneMoveLand() && rec->GetDefendLand())
movesMatch = 0;
if(attacker.IsAtLeastOneMoveWater() && rec->GetDefendWater())
movesMatch = TRUE;
if(attacker.IsAtLeastOneMoveAir() && rec->GetDefendAir())
movesMatch = TRUE;
if(attacker.IsAtLeastOneMoveSpace() && rec->GetDefendSpace())
movesMatch = TRUE;
if(attacker.IsAtLeastOneMoveMountain() && rec->GetDefendMountain())
movesMatch = TRUE;
if(movesMatch) {
if(rec->GetActiveDefenseOnlyWhenCarryingEnablers()) {
sint32 numEnablers = 0;
sint32 i;
for(i = 0; i < m_cargo_list->Num(); i++) {
if(m_cargo_list->Access(i).GetDBRec()->GetEnableCarrierDefenses())
numEnablers++;
}
return numEnablers;
}
return 1;
}
return 0;
}
double UnitData::GetAttack(const UnitRecord *rec, const Unit defender) const
{
MapPoint dpos;
double attack, baseattack;
const UnitRecord *defrec = defender.GetDBRec();
defender.GetPos(dpos);
attack = baseattack = rec->GetAttack();
if(!(rec->GetCanAttack() & defender.GetDBRec()->GetMovementType())) {
return 0;
}
if(defrec->GetWoodenShip()) {
attack += baseattack * rec->GetAttackWoodenShipBonus();
}
if(g_theWorld->GetCell(dpos)->GetCity().m_id != (0)) {
attack += baseattack * rec->GetAttackCityBonus();
}
if(defrec->GetIsSubmarine()) {
attack += baseattack * rec->GetAttackBonusSubmarine();
}
return attack;
}
void UnitData::Bombard(const UnitRecord *rec, Unit defender,
BOOL isCounterBombardment)
{
double prob;
sint32 f = (sint32)(rec->GetFirepower() /
g_theUnitDB->Get(defender.GetType())->GetArmor());
sint32 n;
bool canBombard = rec->GetBombRounds(n);
Assert(canBombard);
if(!canBombard)
n = 0;
double hp = defender.GetHP();
sint32 p;
sint32 i;
g_slicEngine->RunCounterBombardmentTriggers(defender, Unit(m_id));
double defenseStrength = defender.GetDefense(Unit(m_id));
double attack = rec->GetZBRangeAttack();
prob = attack / (attack + defenseStrength);
p = sint32(prob * 100);
double dmr = 1.0/defender.GetHPModifier();
if (IsVeteran())
p += sint32(double(p) * g_theConstDB->GetVetCoef());
for (i=0; iNext(100) < p) {
hp -= f * dmr;
}
}
defender.SetHP(hp);
if(isCounterBombardment) {
g_slicEngine->RunCounterBombardmentTriggers(Unit(m_id), defender);
} else {
g_slicEngine->RunBombardmentTriggers(Unit(m_id), defender);
}
}
void UnitData::BombardOneRound(const UnitRecord *rec, Unit &defender,
double dbonus,
double dmr)
{
sint32 p = rec->GetProbOfBombHit();
sint32 f = rec->GetZBRangeAttack();
double hp = defender.GetHP();
if (IsVeteran())
p += sint32(double(p) * g_theConstDB->GetVetCoef());
p = int (p *(1.0 + dbonus));
if (g_rand->Next(100) < p) {
hp -= f * dmr;
}
defender.SetHP(hp);
}
BOOL UnitData::CanBombardType(const Unit & defender) const
{
const UnitRecord *rec = g_theUnitDB->Get(m_type);
if (rec->GetCanBombardLand() || rec->GetDefendLand()) {
if (defender.GetMovementTypeLand()) {
return TRUE;
}
}
if (rec->GetCanBombardWater() || rec->GetDefendWater()) {
if (defender.GetMovementTypeSea() || defender.GetMovementTypeShallowWater()) {
return TRUE;
}
}
if (rec->GetCanBombardAir() || rec->GetDefendAir()) {
if (defender.GetMovementTypeAir()) {
return TRUE;
}
}
if (rec->GetCanBombardSpace() || rec->GetDefendSpace()) {
if (defender.GetMovementTypeSpace()){
return TRUE;
}
}
if (rec->GetCanBombardMountain() || rec->GetDefendMountain()) {
if (defender.GetMovementTypeMountain()) {
return TRUE;
}
}
return FALSE;
}
BOOL UnitData::Bombard(CellUnitList &defender, BOOL isCounterBombardment)
{
const UnitRecord *rec = g_theUnitDB->Get(m_type);
sint32 i, j, r;
Assert(0 < defender.Num());
r = g_rand->Next(defender.Num());
for (i=r, j=0;
j < defender.Num();
i = ((i + 1) % defender.Num()), j++) {
if(!(defender[i].GetVisibility() & (1 << m_owner)) && !g_theWorld->GetCity(defender[i].RetPos()).IsValid())
continue;
if (CanBombardType(defender[i]) || rec->GetSingleUse())
{
Bombard(rec, defender[i], isCounterBombardment);
return TRUE;
}
}
return FALSE;
}
I'm not a coder but I'm trying to learn, but I cant see where in this code that it only makes bombardment one-square away. Can anyone see where it says that or what the problem is?
Last edited by E on 02-10-2004 at 02:24
|
|
|  |
 |
|
Peter Triggs
|
|
Gone Fishin, Canada
Jan 2000 time: 05:22
|
|
I think this is it:
code:
ORDER_RESULT ArmyData::Bombard(const MapPoint &orderPoint)
{
MapPoint point = orderPoint;
static CellUnitList defender;
defender.Clear();
g_theWorld->GetArmy(point, defender);
sint32 i;
BOOL isSpaceBombard = FALSE;
if(point == m_pos) {
return ORDER_RESULT_ILLEGAL;
} else {
if(!point.IsNextTo(m_pos)) {
return ORDER_RESULT_ILLEGAL;
}
}
When they moved from Civ:CTP to CTP2 they put in a "fire and forget" feature which lets you select a
target and let your army move towards it on its own in order to carry out it's given order. If you want to
re-instate bombarding from a distance you'll have to keep an eye on this.
|
|
|  |
 |
|
E
|
 |
July 24,2005 Ctp2 Tiles in sig!
May 1999 time: 21:22
|
|
quote: Originally posted by Peter Triggs
I think this is it:
code:
ORDER_RESULT ArmyData::Bombard(const MapPoint &orderPoint)
{
MapPoint point = orderPoint;
static CellUnitList defender;
defender.Clear();
g_theWorld->GetArmy(point, defender);
sint32 i;
BOOL isSpaceBombard = FALSE;
if(point == m_pos) {
return ORDER_RESULT_ILLEGAL;
} else {
if(!point.IsNextTo(m_pos)) {
return ORDER_RESULT_ILLEGAL;
}
}
When they moved from Civ:CTP to CTP2 they put in a "fire and forget" feature which lets you select a
target and let your army move towards it on its own in order to carry out it's given order. If you want to
re-instate bombarding from a distance you'll have to keep an eye on this. |
Ok this is where my skills are obviously weak. I'm thinking I need to make the defender's point less than or equal to bombard range value from attacker's point in order to return a true statement and if point is greater tha bombard range than it should return false.
but i don't see code that identifies where the attacker is. Where did this code come from? And I don't see where the code links to bombard effects, firepower (?) and chance of success.
But which file is this in? I'm thinking I can get the data from the nuke and target order to see how to put bombard range in.
Last edited by E on 02-10-2004 at 02:14
|
|
|  |
 |
|
J Bytheway
|
 |
England
Jul 2001 time: 05:22
|
|
quote: Originally posted by E
Ok this is where my skills are obviously weak. I'm thinking I need to make the defender's point less than or equal to bombard range value from attacker's point in order to return a true statement and if point is greater tha bombard range than it should return false.
but i don't see code that identifies where the attacker is. Where did this code come from? And I don't see where the code links to bombard effects, firepower (?) and chance of success.
But which file is this in? I'm thinking I can get the data from the nuke and target order to see how to put bombard range in. |
I'll try to walk you through it.
First thing to note is that you should use [code][/code] tags to surround code to preserve the indenting when you post it here at 'Poly.
code: ORDER_RESULT ArmyData::Bombard(const MapPoint &orderPoint)
This first line says that this code is defining a Bombard method for the class ArmyData. Thus, you can find this code in ArmyData.cpp (that, together with ArmyData.h define the ArmyData class). Each instance of this class represents data about a single army, and also carries these methods to perform actions related to the army (like bombarding),
This function takes just one argument, orderPoint, which is of type MapPoint. This represents the position on the map being bombarded.
code: {
MapPoint point = orderPoint;
The code immediately defines a local variable called point and copies the position being bombarded into it.
code: static CellUnitList defender;
defender.Clear();
g_theWorld->GetArmy(point, defender);
Now the code fetches any army which might exist at this location.
code: sint32 i;
BOOL isSpaceBombard = FALSE;
the isSpaceBombard variable is probably a leftover from CTP space bombers.
code: if(point == m_pos) {
return ORDER_RESULT_ILLEGAL;
The first check here tests whether the army is trying to bombard itself - the variable m_pos is a member variable of the ArmyData class which stores the location of this army, you can see it defined in ArmyData.h. If the location of this army is the same as the location being bombarded, then give up and say the order is illegal.
code: } else {
if(!point.IsNextTo(m_pos)) {
return ORDER_RESULT_ILLEGAL;
}
}
Otherwise, this next check uses the IsNextTo method of MapPoint to test whether the point being bombarded is next to the position of this army. If it isn't, the order is declared illegal.
And so forth...
|
|
|  |
 |
|
E
|
 |
July 24,2005 Ctp2 Tiles in sig!
May 1999 time: 21:22
|
|
from \ctp2_code\gs\world\mappoint.cpp
code:
BOOL MapPoint::IsNextTo(const MapPoint &neighbor) const
{
static MapPoint tmp;
if(GetNeighborPosition(NORTH,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(NORTHWEST,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(NORTHEAST,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(SOUTH,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(SOUTHWEST,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(SOUTHEAST,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(WEST,tmp))
if (neighbor == tmp) return TRUE;
if(GetNeighborPosition(EAST,tmp))
if (neighbor == tmp) return TRUE;
return FALSE;
}
struct ScreenPoint
{
ScreenPoint(const MapPoint &mp)
{
x = 2 * mp.x + mp.y;
y = mp.y;
if (x >= 2 * g_mp_size.x)
x -= 2 * g_mp_size.x;
}
sint32 x, y;
};
static sint32 WrapDelta(sint32 delta, sint32 size)
{
if (delta > 0)
{
if (2*delta > size)
delta -= size;
}
else
{
if (-2*delta > size)
delta += size;
}
return delta;
}
I'm thinking if I add a math function that involves less than or equal bombard range, I can make a WithinRange function that will restore bombard range...
Last edited by E on 02-10-2004 at 02:54
|
|
|  |
 |
|
Solver
|
|
Apolyton Duke Of Something
|
 |
Latvia, Riga
Sep 2000 time: 07:22
|
|
ArmyData:BombardCity seems of interest as it has the (unused apparently) possibilities of damaging citizens/buildings during city bombardment.
The code I was referring to, though, is after all what is in the first post, specifically:
code:
sint32 UnitData::CanBombard(CellUnitList &defender) const
{
const UnitRecord *rec = g_theUnitDB->Get(m_type);
double r = rec->GetBombardRange() + 0.5;
double rsq = r * r;
MapPoint dpos;
defender.GetPos(dpos);
if(GetDistance(dpos, m_pos, (sint32)r) > rsq)
return FALSE;
So, it does check for whether the target is in the distance. I'm not sure if GetDistance > rsq will not return FALSE in some cases where it should actually return TRUE... but point is, all the code for ranged bombard is still there. I haven't found, however, where it tells the unit to move to its target before bombarding if there's a distance between them - disabling that is a must.
|
|
|  |
 |
|
Solver
|
|
Apolyton Duke Of Something
|
 |
Latvia, Riga
Sep 2000 time: 07:22
|
|
Well, I did run into that problem. The code gives squared distance there. And one should never let me anywhere near geometrical applications of coding or algebra .
Problem: suppose a cannon with a bombard range of 2. A target standing two tiles ahead. Range=2, r=2.5, rsq=6.25. Since the target is in range, GetDistance should return something less than 6.25. However, the exact way that GetDistance works is something I don't understand really, and I can't check with the code right now.
Why is it using a squared distance anyway, and adds 0.5 to the bombard range? Can't there be a linear function for getting distance that treats all adjacent squares as distance=1, the ones adjacent to those as distance=2, and so on?
|
|
|  |
 |
|
E
|
 |
July 24,2005 Ctp2 Tiles in sig!
May 1999 time: 21:22
|
|
code:
sint32 UnitData::GetDistance(UnitData* unit1, UnitData* unit2,
sint32 wrapRange)
{
MapPoint u2pos = unit2->m_pos;
return GetDistance(unit1, u2pos, wrapRange);
}
sint32 UnitData::GetDistance(Installation &inst, UnitData* unit2,
sint32 wrapRange)
{
MapPoint iPos;
inst.GetPos(iPos);
return GetDistance(unit2, iPos, wrapRange);
}
sint32 UnitData::GetDistance(const UnitData* unit, const MapPoint &pos,
sint32 wrapRange)
{
MapPoint uPos;
unit->GetPos(uPos);
return GetDistance(uPos, pos, wrapRange);
}
sint32 UnitData::GetDistance(const MapPoint &uPos, const MapPoint &pos,
sint32 wrapRange)
{
return MapPoint::GetSquaredDistance(uPos, pos);
|
|
|  |
 |
|  |
 |
|  |
All times are GMT. The time now is 05:22. Apolyton Time is 00:22. |
top of page
|
|
|
Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is ON
vB code is ON
Smilies are ON
[IMG] code is ON
|
|
|
|
|
|