Related
I have a custom QGraphicsItemGroup, with fixed set of children items. I need to make it resizable(already done), but, while resizing, boundingRect is not updating -- though, all child items are drawn correctly. I've tried adding prepareGeometryChange() and update() in different places of the program, but that hasn't helped.
Even this implementation returns default boundingRect:
QRectF FigureGraphicsItemGroup::boundingRect() const
{
return childrenBoundingRect().adjusted(0, 0, 50, 0);
}
And some necessary code(NB no custom painting):
m_right: right control for resize.
QRectF FigureGraphicsItemGroup::boundingRect() const
{
return childrenBoundingRect();
}
void FigureGraphicsItemGroup::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
QPointF pos = event->pos();
if (m_right->contains(pos) && m_right->isVisible())
{
m_isResized = true;
}
else
QGraphicsItemGroup::mousePressEvent(event);
}
void FigureGraphicsItemGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QPointF pos = event->pos();
if (m_isResized)
{
if (m_previous.x() == -1 && m_previous.y() == -1)
m_previous = pos;
m_delta = pos.x() - m_previous.x();
m_previous = pos;
QGraphicsItem::prepareGeometryChange();
recalculatePositions();
}
else
{
QGraphicsItemGroup::mouseMoveEvent(event);
}
}
void FigureGraphicsItemGroup::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
QPointF pos = event->pos();
if (m_right->contains(pos) && m_right->isVisible())
{
setCursor(Qt::SizeHorCursor);
}
else
{
setCursor(Qt::ArrowCursor);
QGraphicsItemGroup::hoverMoveEvent(event);
}
}
void FigureGraphicsItemGroup::reset()
{
m_isResized = false;
m_delta = 0;
m_previous = QPointF(-1 , -1);
}
void FigureGraphicsItemGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event)
reset();
QGraphicsItemGroup::mouseReleaseEvent(event);
}
QVariant FigureGraphicsItemGroup::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change)
{
case ItemSelectedHasChanged:
m_isSelected = isSelected();
m_right->setVisible(m_isSelected);
break;
}
return QGraphicsItem::itemChange(change, value);
}
void FigureGraphicsItemGroup::recalculatePositions()
{
int sumX = 1;
QFontMetrics fm(m_zoneNumberSimpleTextItem->font());
m_routeNumberSimpleTextItem->setPos(sumX, m_middle - fm.height());
sumX += m_routeNumberSimpleTextItem->boundingRect().width() * SPACING;
//-------------------------------------------------------------------------------------------
int diameter = fm.height() * SPACING;
int pixLength = fm.width(m_zoneNumberSimpleTextItem->text());
if (pixLength > diameter)
diameter = pixLength;
QPen pen(Qt::red);
pen.setWidth(1);
m_zoneCircleEllipseItem->setRect(sumX, m_middle - diameter, diameter, diameter);
m_zoneCircleEllipseItem->setPen(pen);
m_zoneNumberSimpleTextItem->setPos(sumX + fm.width(m_zoneNumberSimpleTextItem->text()) / 2,
m_middle - fm.height());
sumX += m_zoneCircleEllipseItem->boundingRect().width() * SPACING;
//-------------------------------------------------------------------------------------------
m_fuelSimpleTextItem->setPos(sumX, m_middle * 1.1);
//-------------------------------------------------------------------------------------------
m_leftCornerSvgItem->setPos(sumX, m_middle - m_leftCornerSvgItem->boundingRect().height() / 4);
sumX += m_leftCornerSvgItem->boundingRect().width() * m_scale;
//-------------------------------------------------------------------------------------------
pen.setColor(m_blue);
pen.setWidth(4);
m_leftLineItem->setPen(pen);
int length = m_leftLineItem->line().length() + m_delta / 2;
length = length < 0 ? 0 : length;
m_leftLineItem->setLine(sumX, m_middle, sumX + length, m_middle);
sumX += m_leftLineItem->boundingRect().width();
//-------------------------------------------------------------------------------------------
m_exerciseSvgItem->setPos(sumX - 2, m_middle - m_exerciseSvgItem->boundingRect().height() / 4);
sumX += m_exerciseSvgItem->boundingRect().width() * m_scale;
//-------------------------------------------------------------------------------------------
pen.setColor(m_blue);
pen.setWidth(4);
m_rightLineItem->setPen(pen);
length = m_rightLineItem->line().length() + m_delta / 2;
length = length < 0 ? 0 : length;
m_rightLineItem->setLine(sumX , m_middle, sumX + length, m_middle);
sumX += m_rightLineItem->boundingRect().width();
//-------------------------------------------------------------------------------------------
m_rightCornerSvgItem->setPos(sumX - 2, m_middle - m_rightCornerSvgItem->boundingRect().height() / 4);
sumX += m_rightCornerSvgItem->boundingRect().width() * m_scale;
//-------------------------------------------------------------------------------------------
m_right->setRect(sumX, m_middle, 4, 4);
//-------------------------------------------------------------------------------------------
}
UPD
A little hack helped me: just add removeFromGroup & addToGroup of some item during resize -- and boundingRect will be drawn correctly. But it looks a little bit strange.
I'm working on a cellular automaton where changes happen in every rounds. Obviously, I made a loop for it - basically it works, fortunately, but if I want to add another type of cells to the map, one type of cells works, but the other doesn't do anything: the game begins and e.g. in this example, the Conway-automaton starts growing, but the red test-cells are just staying without any changes.
#define fldwidth 110
#define fldheight 140
typedef struct tiles
{
unsigned char red, green, blue;
}tiles;
const tiles TEST_ALIVE = {255,0,0};
const tiles TEST_DEAD = {50,0,0};
const tiles CONWAY_ALIVE = {0,255,0};
const tiles CONWAY_DEAD = {0,50,0};
//Maes módszere a struktúrák egyenlőségének vizsgálatára
bool equality(tiles* a, const tiles* b)
{
if (a->red == b->red && a->green == b->green && a->blue == b->blue)
{
return true;
} else {
return false;
}
}
//sejttípus 1.: tesztsejt: minden magányos vagy túlbuzgó sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &TEST_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &TEST_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &TEST_ALIVE) == false && counter >= 2)
{
arrb[i][j] = TEST_ALIVE;
}
if (equality(&arra[i][j], &TEST_ALIVE) == true && (counter == 0 || counter > 6))
{
arrb[i][j] = TEST_DEAD;
}
}
}
}
//sejttípus 2.: Conway életjátéka
void Conway(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &CONWAY_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &CONWAY_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &CONWAY_ALIVE) == false && counter == 3)
{
arrb[i][j] = CONWAY_ALIVE;
}
if (equality(&arra[i][j], &CONWAY_ALIVE) == true && (counter != 2 && counter != 3))
{
arrb[i][j] = CONWAY_DEAD;
}
}
}
}
This is content of the loop:
Test(fielda,fieldb);
Conway(fielda,fieldb);
end = false;
round++;
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
fielda[i][j] = fieldb[i][j];
}
}
As I mentioned, in this example, Conway cells grow, but Test cells just stay. How to make them work simultaneously?
(I use Allegro libraries so if that has something for this problem, feel free to share with me!)
Test(fielda,fieldb); sets every cell of fieldb based on the current value of fielda. And then Conway(fielda,fieldb); sets every cell of fieldb based on the current value of fielda, overwriting fieldb so that everything Test did is gone. One way to fix this is to change your loop to:
Test(fielda,fieldb);
Conway(fieldb,fielda); //switched the parameters
end = false;
round++;
//there is no need to copy fieldb to fielda here because Conway already did
But this might not be the right fix depending on exactly how you want test and conway to interact with each other.
I'm working on a cellular automaton where changes happen in every rounds. Obviously, I made a loop for it - basically it works, fortunately, but if I want to add another type of cells to the map, the whole thing doesn't work! I mean, one type of cells works, but the other doesn't do anything: The game begins and e.g. in this example, the Conway-automaton starts growing, but the red test-cells are just staying without any changes.
These are the two functions (with predefined things):
#define fldwidth 110
#define fldheight 140
//struktúra, aztán a sejtek definíciója
typedef struct tiles
{
unsigned char red, green, blue;
}tiles;
const tiles TEST_ALIVE = {255,0,0};
const tiles TEST_DEAD = {50,0,0};
const tiles CONWAY_ALIVE = {0,255,0};
const tiles CONWAY_DEAD = {0,50,0};
//Maes módszere a struktúrák egyenlőségének vizsgálatára
bool equality(tiles* a, const tiles* b)
{
if (a->red == b->red && a->green == b->green && a->blue == b->blue)
{
return true;
} else {
return false;
}
}
//sejttípus 1.: tesztsejt: minden magányos vagy túlbuzgó sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &TEST_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &TEST_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &TEST_ALIVE) == false && counter >= 2)
{
arrb[i][j] = TEST_ALIVE;
}
if (equality(&arra[i][j], &TEST_ALIVE) == true && (counter == 0 || counter > 6))
{
arrb[i][j] = TEST_DEAD;
}
}
}
}
//sejttípus 2.: Conway életjátéka
void Conway(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &CONWAY_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &CONWAY_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &CONWAY_ALIVE) == false && counter == 3)
{
arrb[i][j] = CONWAY_ALIVE;
}
if (equality(&arra[i][j], &CONWAY_ALIVE) == true && (counter != 2 && counter != 3))
{
arrb[i][j] = CONWAY_DEAD;
}
}
}
}
and this is the loop itself:
while(!end)
{
al_wait_for_event_timed(event_queue,&asd,0.001); //várakozás
if(asd.type == ALLEGRO_EVENT_KEY_DOWN)
{
if(asd.keyboard.keycode == ALLEGRO_KEY_ENTER)
{
Test(fielda,fieldb);
Conway(fielda,fieldb);
end = false;
round++;
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
fielda[i][j] = fieldb[i][j];
}
}
}
}
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
al_draw_filled_rectangle(20 + (4*i), 20 + (4*j), 24 + (4*i), 24 + (4*j), al_map_rgb(fielda[i][j].red, fielda[i][j].green, fielda[i][j].blue));
}
}
}
Can you tell me what is wrong with it? Or maybe the problem is not in the loop?
Your problem is that the second function you call reverses all the changes made by the first function. That is why you see only one working.
The best way to get both working it to let each function operate only on one colour channel. Test uses only the red colour channel (both for reading and changing), while Conway uses only the green colour channel. Be prepared to see cells with different colours: these were affected by both functions.
I'm having a really bad time here looking for the error in my code.
My collision detection won't work here even the algorithm I searched in Google.
void PollEvents()
{
for (int i = 0;i < NUMBER_OF_BLOCKS; ++i)
{
Rectangle& a = blocks[i];
if (mouse.state == GLFW_PRESS)
{
//look for any block to grab
if (mouse.leftClick && !blocks[selectedBlock].Grab() &&
a.Hover(mouse.pos.x, mouse.pos.y))
{
//prevent grabbing another block
if (i != selectedBlock) {
selectedBlock = i;
}
a.Grab() = true;
if (a.IsTypeHorizontal()) {
diff = mouse.pos.x - a.Left();
} else {
diff = mouse.pos.y - a.Top();
}
}
if (a.Grab())
{
for (int j = 0;j < NUMBER_OF_BLOCKS; ++j)
{
//skip for any self-checking
if (i == j) continue;
Rectangle& b = blocks[j];
//check for rectangle collision
if (!a.Collide(b) || b.Collide(a)) {
//j++;
//how does this block will move.
if (a.IsTypeVertical()) {
a.SetY(mouse.pos.y - diff);
} else {
a.SetX(mouse.pos.x - diff);
}
} else {
switch (a.sideHit)
{
case UP:
//a.SetY(b.Bottom());
printf("UP\n");
break;
case DOWN:
//a.SetY(b.Top() + a.GetHeight());
printf("DOWN\n");
break;
case LEFT:
//a.SetX(b.Right());
printf("LEFT\n");
break;
case RIGHT:
//a.SetX(b.Left() - a.GetWidth());
printf("RIGHT\n");
break;
}
}
//check for bound collision
a.BoundCheck(1.f);
}
}
} else {
a.Grab() = false;
}
}
}
Collision detection:
bool Rectangle::Collide(const Rectangle& r) {
if (IsTypeHorizontal()) {
if (r.Hover(Left(), Top()) && r.Hover(Right(), Top())) {
sideHit = UP;
return true;
} else if (r.Hover(Right(), Bottom()) && r.Hover(Left(), Bottom())) {
sideHit = DOWN;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = DOWN;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = DOWN;
// return true;
// }
} else {
if (r.Hover(Left(), Top()) && r.Hover(Left(), Bottom())) {
sideHit = LEFT;
return true;
} else if (r.Hover(Right(), Top()) && r.Hover(Right(), Bottom())) {
sideHit = RIGHT;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = RIGHT;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = RIGHT;
// return true;
// }
}
return false;
}
Code for Hover:
inline float Hover(float X, float Y) const {
return X >= Left() &&
X <= Right() &&
Y >= Bottom() &&
Y <= Top();
}
I'm trying to make my own unblockme.
Please help me on my collision-detection. It's been 3 days now since I got stuck in this problem.
UPDATE
I have found out the problem why all rect-rect collision detection won't work in my program.
Bug:
if (!a.Collide(b)) {
//Move()
} else {
//Resolve collision
}
This one should be
if (!Rectangle::Collide(a, b)) {
//Move()
} else {
//Resolve collision
}
Making the Collide() a static member of Rectangle because, as you can see in my implementation of Collide(), it bases its decision on its own member so a.Hover(b.x, b.y) doesn't make any sense.
Hope this helps a little bit to all newbies like me.
To do rect/rect collision detection, if any of one (edges parallel to x and y axis) rect's four points is inside the other rect, we have a collision.
An easier way than to check each of the four points is to check if one X edge is between both the other rect's X edges, and if one Y edge is between both the other rect's Y edges - if both are true, we have a collision (because the two edges must meet at a point inside of the other rect). So we just check this in both directions:
bool isclamped(float mid, float A, float B)
{
if (A > B)
{
return mid >= B && mid <= A;
}
return mid >= A && mid <= B;
}
bool checkcollisiononeway(rect rectA, rect rectB)
{
if (isclamped(rectA.left, rectB.left, rectB.right)
|| isclamped(rectA.right, rectB.left, rectB.right))
&& (isclamped(rectA.bottom, rectB.bottom, rectB.top)
|| isclamped(rectA.top, rectB.bottom, rectB.top))
{
return true;
}
return false;
}
bool checkcollisionbothways(rect rectA, rect rectB)
{
return checkcollisiononeway(rectA, rectB) || checkcollisiononeway(rectB, rectA);
}
To determine the angle of collision after detecting a collision, find the angle between their two centers using atan2(rectA.y - rectB.y, rectA.x - rectB.x) (the angle is returned in radians, not in degrees)
I have been trying to fix this problem for a few weeks now but nothing I have done has fixed it. This seems to be a problem with the Intellisense information not being updated in a .cpp file.
The problem is that class reference passes for specific classes in a header file are not being recognized but Intellisense only in the cpp file. In the Header file the references are read perfectly.
Here is the header file, excuse some of the mess as I am in the middle of reorganizing, merging functions, and reworking the class:
#ifndef DAMAGE_H
#define DAMAGE_H
#include <string>
#include "entity.h"
#include "hardPoint.h"
#include <vector>
using std::string;
using std::vector;
class Damage
{
public:
Damage();
float findDType(string dType, float damage);
void dmgProcessing(bAttacker& bAttacker, bTarget& bTarget);
float dTPiercing1(float damage);
float dTPiercing2(float damage);
float dTPiercing3(float damage);
float dTNapalm1(float damage);
float dTNapalm2(float damage);
float dTNapalm3(float damage);
float dTDesructor(float damage);
float dTNanite1(float damage);
float dTNanite2(float damage);
float dTNanite3(float damage);
float dTDDay1(float damage);
float dTDDay2(float damage);
float dTStealth(float damage);
float dTFOnly(float damage);
float dTEMP1(float damage, Player& mPlayer, Hostile args[], string target);
float dTEMP2(float damage, Player& mPlayer, Hostile args[], string target);
float dTEMP3(float damage, Player& mPlayer, Hostile args[], string target);
float dTVirus1();
float dTVirus2();
float dTVirus3();
float dTVirus4();
float dTMAccel(float damage);
void bPAttack(bool allout, bool spread, bool wsystem, bool single);
void setupWQueue(bAttacker& bAttacker, string atype);
void cleanWQueue();
float processWQueue(bAttacker& bAttacker, bTarget& bTarget);
float processSDamage(bTarget& bTarget, string wdtype);
float processSecDamage(bTarget& bTarget);
void setupBAT(Entity* entity1, Entity* entity2);
bool getSDNTurns();
bool getSDNANTurns();
private:
vector<hardPoint> weaponQueue;
float vDamage; //Vanilla Damage
float mDamage; //Modified Damage
float fDamage; //Final Damage
float sDamage; //Secondary Damage
float tSDamage; //total secodary damage
int i;
int sDNTurns, sDNANTurns; //Number of turns to apply secondary damage for (N = Napalm, NAN = Nanite)
int dLow, dHigh;
string wdtype; //store weapon name
int nSDamage, nADamage, nHDamage; //Health interface variables for nanite secondary damage
};
//#endif
/*Damage Types:
piercing1: Armor Piercing, does not affect hull
piercing2: Hull Piercing, does not affect armor
piercing3: Armor and Hull piercing
napalm1: low level napalm damage, lasts two turns
napalm2: medium level napalm damage, lasts four turns
napalm3: high level napalm damage, lasts six turns
destructor: higher damage to defenses
nanite1: low level nanite damage, does 5% of HP damage for two turns
nanite2: medium level nanite damage, does 8% of HP damage for four turns
nanite3: high level nanite damage, does 15% of HP damage for eight turns
doomsday1: large scale damage, kills off 25% of population instantly along with 15% of all infrastructure and 10% of biomass
doomsday2: larger scale damage, kills off 40% of population instantly along with 25% of all infrastructure and 18% of biomass
stealth: invisible to point defenses, point defenses will still have a 2% chance to destroy a missile volley per point defense up to 10%.
frigonly: only damages frigate class ships, no damage to higher classes
null: no special damage
emp1: low level shield damage, if shields down will cripple non-emp protected target for one turn
emp2: medium level shield damage, if shields down will cripple non-emp protected target for three turns
emp3: high level shield damage, if shields down will cripple non-emp protected target for seven turns
virus1: scrambles targeting systems of enemy ship, target will not attack for two turns and loses shields
virus2: scrambles targeting systems and crashes computer, target will not attack for five turns and loses shields
virus3: scrambles targeting systems, crashes computer, and disables life support and loses shields (RTS/RPG). Crews of ships lower then crusier class can be killed in two turns and ship can be salvaged whole (twice the resources; RTS only)
virus4: crashes all systems and injects core breach code into engines and loses shields. 35% chance that the ship will self destruct over 4 turns, after which systems reboot and core breach stopped. 10% chance per 20 tech crewmen or 5 tech module on board to avert code breach. (RTS only)
massaccel: Mass Accelerator damage bypasses shield and armor and deals direct hull damage.
*/
class bTarget
{
public:
bTarget();
void getShip(Entity* entity);
Ship returnShip(Entity* entity);
Ship* Ship;
};
class bAttacker
{
public:
bAttacker();
void getShip(Entity* entity);
Ship returnShip(Entity* entity);
Ship* Ship;
};
#endif
All of the reference passes pertaining to bTarget and bAttacker are find in this header file but once I place the function definitions into the .cpp file Intellisense bombs out by claiming that the definitions do not match the header declaration of void setupWQueue(error-type &bAttacker, string atype) just as an example.
However direct access to the bAttacker and bTarget classes, for the definition of the getShip function for example, are just fine.
Edit:
For the sake of being thorough in case something in it is causing this here is the cpp file as well; this will be much messier than the header for the same reason (sorry!):
#include <string>
#include "damage.h"
#include "planet.h"
#include "random.h"
#include "datasystem.h"
using namespace std;
#define EMP1DT 1
#define EMP2DT 3
#define EMP3DT 7
#define NP1P 0.15
#define NAN1P 0.05
#define NP2P 0.28
#define NAN2P 0.08
#define NP3P 0.46
#define NAN3P 0.15
#define NP1T 2
#define NAN1T 2
#define NP2T 4
#define NAN2T 4
#define NP3T 6
#define NAN3T 8
dataSystem ds;
int test = NAN1T;
Damage::Damage()
{
}
void Damage::dmgProcessing(bAttacker& bAttacker, bTarget& bTarget)
{
setupWQueue(bAttacker, atype);
}
float Damage::dTEMP1(float damage, Player& mPlayer, Hostile args[], string target)
{
if (target == mPlayer.getName()) //Consider creating main class or matrix for all fighting entities/teams to make this easier
{
if ((!mPlayer.Ship.isDisabled()) && (mPlayer.Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
mPlayer.Ship.disableShip(EMP1DT);
}
else if ((mPlayer.Ship.getShieldStatus()) && (mPlayer.Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(8,10);
return mDamage;
}
}
else
{
for (i = 0; i <= sizeof(args)-1; i++)
{
if (target == args[i].getName())
{
if ((!args[i].Ship.isDisabled()) && (args[i].Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
args[i].Ship.disableShip(EMP1DT);
}
else if ((args[i].Ship.getShieldStatus()) && (args[i].Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(8,10);
return mDamage;
}
}
}
}
}
float Damage::dTEMP2(float damage, Player& mPlayer, Hostile args[], string target)
{
if (target == mPlayer.getName()) //Consider creating main class or matrix for all fighting entities/teams to make this easier
{
if ((!mPlayer.Ship.isDisabled()) && (mPlayer.Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
mPlayer.Ship.disableShip(EMP2DT);
}
else if ((mPlayer.Ship.getShieldStatus()) && (mPlayer.Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(5,7);
return mDamage;
}
}
else
{
for (i = 0; i <= sizeof(args)-1; i++)
{
if (target == args[i].getName())
{
if ((!args[i].Ship.isDisabled()) && (args[i].Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
args[i].Ship.disableShip(EMP2DT);
}
else if ((args[i].Ship.getShieldStatus()) && (args[i].Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(5,7);
return mDamage;
}
}
}
}
}
float Damage::dTEMP3(float damage, Player& mPlayer, Hostile args[], string target)
{
if (target == mPlayer.getName()) //Consider creating main class or matrix for all fighting entities/teams to make this easier
{
if ((!mPlayer.Ship.isDisabled()) && (mPlayer.Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
mPlayer.Ship.disableShip(EMP3DT);
}
else if ((mPlayer.Ship.getShieldStatus()) && (mPlayer.Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(2,4);
return mDamage;
}
}
else
{
for (i = 0; i <= sizeof(args)-1; i++)
{
if (target == args[i].getName())
{
if ((!args[i].Ship.isDisabled()) && (args[i].Ship.getSShield() == 0)) //If ship is not disabled already and shilds are 0
{
args[i].Ship.disableShip(EMP3DT);
}
else if ((args[i].Ship.getShieldStatus()) && (args[i].Ship.getSShield() != 0)) //If shields are enabled and are greater then 0
{
mDamage = damage / Random(2,4);
return mDamage;
}
}
}
}
}
void Damage::bPAttack(bool allout, bool spread, bool wsystem, bool single)
{
vDamage = 0.0f;
mDamage = 0.0f;
fDamage = 0.0f;
if (allout)
{
fDamage = processWQueue(bAttacker);
//Check for secondary damage
if (getSDNTurns())
{
fDamage += processSecDamage(bAttacker);
sDNTurns -= 1;
}
if (getSDNANTurns())
{
fDamage += processSecDamage(bAttacker);
sDNANTurns -= 1;
}
hostile.takeSDamage(fDamage);
}
else if (spread)
{
}
else if (wsystem)
{
}
else if (single)
{
}
}
float Damage::processWQueue(bAttacker& bAttacker,bTarget& bTarget)
{
for (i = 0; i < weaponQueue.size(); i++)
{
if (weaponQueue.at(i).getHPWType() == "laser")
{
wdtype = bAttacker.Ship->getLWDType(weaponQueue.at(i).getHPSlot()); //send slot of current laser weapon to ship for return of item name
dLow = bAttacker.Ship->lBanks.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRLow();
dHigh = bAttacker.Ship->lBanks.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRHigh();
}
else if (weaponQueue.at(i).getHPWType() == "missile")
{
wdtype = bAttacker.Ship->getMWDType(weaponQueue.at(i).getHPSlot()); //send slot of current missile weapon to ship for return of item name
dLow = bAttacker.Ship->mTurrets.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRLow();
dHigh = bAttacker.Ship->mTurrets.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRHigh();
}
else if (weaponQueue.at(i).getHPWType() == "bomb")
{
wdtype = bAttacker.Ship->getBWDType(weaponQueue.at(i).getHPSlot()); //send slot of current bomb weapon to ship for return of item name
dLow = bAttacker.Ship->bHolds.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRLow();
dHigh = bAttacker.Ship->bHolds.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRHigh();
}
else if (weaponQueue.at(i).getHPWType() == "rail")
{
wdtype = bAttacker.Ship->getRWDType(weaponQueue.at(i).getHPSlot()); //send slot of current rail gun weapon to ship for return of item name
dLow = bAttacker.Ship->rMounts.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRLow();
dHigh = bAttacker.Ship->rMounts.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRHigh();
}
else if (weaponQueue.at(i).getHPWType() == "heavy")
{
wdtype = bAttacker.Ship->getHWDType(weaponQueue.at(i).getHPSlot()); //send slot of current heavy weapon to ship for return of item name
dLow = bAttacker.Ship->hWBays.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRLow();
dHigh = bAttacker.Ship->hWBays.at(weaponQueue.at(i).getHPSlot()).hpWeapon.getWDRHigh();
}
if (wdtype != "null")
{
vDamage += Random(dLow, dHigh);
mDamage += processSDamage(bTarget,wdtype);
}
else
{
vDamage += Random(dLow, dHigh);
}
}
return vDamage;
}
float Damage::processSDamage(bTarget& bTarget, string wdtype)
{
if (wdtype == "napalm1")
{
if (sDamage > 0.0f)
{
sDamage += (0.50 * (vDamage * NP1P));
}
else
{
sDamage = vDamage * NP1P;
}
if (sDNTurns < NP1T)
{
sDNTurns = NP1T;
}
}
else if (wdtype == "napalm2")
{
if (sDamage > 0.0f)
{
sDamage += (0.50 * (vDamage * NP2P));
}
else
{
sDamage = vDamage * NP2P;
}
if (sDNTurns < NP2T)
{
sDNTurns = NP2T;
}
}
else if (wdtype == "napalm3")
{
if (sDamage > 0.0f)
{
sDamage += (0.50 * (vDamage * NP3P));
}
else
{
sDamage = vDamage * NP3P;
}
if (sDNTurns < NP3T)
{
sDNTurns = NP3T;
}
}
else if (wdtype == "nanite1")
{
if (nSDamage > 0.0f)
{
nSDamage += (0.75 * (bTarget.Ship->getSShield() * NAN1P));
}
else
{
nSDamage = bTarget.Ship->getSShield() * NAN1P;
}
if (nADamage > 0.0f)
{
nADamage += (0.75 * (bTarget.Ship->getSShield() * NAN1P));
}
else
{
nADamage = bTarget.Ship->getSShield() * NAN1P;
}
if (nHDamage > 0.0f)
{
nHDamage += (0.75 * (bTarget.Ship->getSShield() * NAN1P));
}
else
{
nHDamage = bTarget.Ship->getSShield() * NAN1P;
}
if (sDNANTurns < NAN1T)
{
sDNANTurns = NAN1T;
}
}
else if (wdtype == "nanite2")
{
if (nSDamage > 0.0f)
{
nSDamage += (0.75 * (bTarget.Ship->getSShield() * NAN2P));
}
else
{
nSDamage = bTarget.Ship->getSShield() * NAN2P;
}
if (nADamage > 0.0f)
{
nADamage += (0.75 * (bTarget.Ship->getSShield() * NAN2P));
}
else
{
nADamage = bTarget.Ship->getSShield() * NAN2P;
}
if (nHDamage > 0.0f)
{
nHDamage += (0.75 * (bTarget.Ship->getSShield() * NAN2P));
}
else
{
nHDamage = bTarget.Ship->getSShield() * NAN2P;
}
if (sDNANTurns < NAN2T)
{
sDNANTurns = NAN2T;
}
}
else if (wdtype == "nanite3")
{
if (nSDamage > 0.0f)
{
nSDamage += (0.75 * (bTarget.Ship->getSShield() * NAN3P));
}
else
{
nSDamage = bTarget.Ship->getSShield() * NAN3P;
}
if (nADamage > 0.0f)
{
nADamage += (0.75 * (bTarget.Ship->getSShield() * NAN3P));
}
else
{
nADamage = bTarget.Ship->getSShield() * NAN3P;
}
if (nHDamage > 0.0f)
{
nHDamage += (0.75 * (bTarget.Ship->getSShield() * NAN3P));
}
else
{
nHDamage = bTarget.Ship->getSShield() * NAN3P;
}
if (sDNANTurns < NAN1T)
{
sDNANTurns = NAN3T;
}
}
}
float Damage::processSecDamage(bTarget& bTarget)
{
if (getSDNTurns())
{
tSDamage += sDamage;
}
if (getSDNANTurns())
{
//Direct damage
bTarget.Ship->setSShield(bTarget.Ship->getSShield()-nSDamage);
bTarget.Ship->setSArmor(bTarget.Ship->getSArmor()-nADamage);
bTarget.Ship->setSHull(bTarget.Ship->getSHull()-nHDamage);
}
return tSDamage;
}
bool Damage::getSDNTurns()
{
return sDNTurns > 0;
}
bool Damage::getSDNANTurns()
{
return sDNANTurns > 0;
}
void Damage::setupWQueue(bAttacker& bAttacker, string atype)
{
cleanWQueue(); //Clear vector
if (atype == "allout")
{
for (i = 0; i < bAttacker.Ship->getWVSize(); i++)
{
weaponQueue.push_back(bAttacker.Ship->getSHPoint(i));
}
}
else if (atype == "spread")
{
for (i = 0; i < bAttacker.Ship->getSSize(); i++)
{
weaponQueue.push_back(bAttacker.Ship->getSHPoint(i));
}
}
else if (atype == "wsystem")
{
for (i = 0; i < bAttacker.Ship->getWVSize(); i++)
{
weaponQueue.push_back(bAttacker.Ship->getSHPoint(i));
}
}
else if (atype == "single")
{
weaponQueue.push_back(bAttacker.Ship->getWVHPoint(0));
}
}
void Damage::cleanWQueue()
{
weaponQueue.clear();
}
void Damage::setupBAT(Entity* entity1, Entity* entity2)
{
bAttacker bAttacker;
bTarget bTarget;
bAttacker.getShip(entity1);
bTarget.getShip(entity2);
dmgProcessing(bAttacker, bTarget);
}
//bAttacker
void bAttacker::getShip(Entity* entity)
{
Ship = entity->Ship.rShip(); //Create an easy to use interface to get the ship data
}
//bTarget
void bTarget::getShip(Entity* entity)
{
Ship = entity->Ship.rShip();
}
I finally gave up and just moved and combined bAttacker and bTarget into a new class called bEntity (battle entity) and referenced it twice to create two instances of bEntity for both the Target and Attacker identifiers.
Works fine that way, I suppose the problem was in that you cannot define multiple non-related classes and access them normally (you can do that but the main class has to have a reference or pointer to the other classes in the header).
Another reason might be because I forgot the constructors in the cpp file for bAttacker and bTarget but I like my new set up better anyway, much more compact.