Announcement

Collapse
No announcement yet.

Increasing Bombardment Range

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #61
    Thanks a lot Fromafar. I had previously looked through the gameevent code, but not found the right place to look.

    ArmyData::PerformOrderHere looks interesting. I'm not sure, but I hope I'll have time in some three hours to look at it. There are, as I see it, several ways to change bombard to range. First - pay attention to the order_rec->GetRange(range); line and modify the GEV_BOMBARD order to have its range equal to bombarding unit's bombard range. Other ways seem to be not so clean, so this way is, I am sure, the best, just gotta check the OrderRecord or whatever class it is then.

    I am not sure yet, but I suspect that it might create a situation where the game wouldn't let ranged bombard units bombard targets they couldn't reach (such as over a strip of water they can't cross).

    If I have time this evening, I'll report on my findings in ~4 hours.
    Solver, WePlayCiv Co-Administrator
    Contact: solver-at-weplayciv-dot-com
    I can kill you whenever I please... but not today. - The Cigarette Smoking Man

    Comment


    • #62
      Solver,

      Any luck or is it related to not being able to compile again?
      Formerly known as "E" on Apolyton

      See me at Civfanatics.com

      Comment


      • #63
        Able to compile here and all is fine. Just hit a little snag now, but that's to be fixed soon.
        Solver, WePlayCiv Co-Administrator
        Contact: solver-at-weplayciv-dot-com
        I can kill you whenever I please... but not today. - The Cigarette Smoking Man

        Comment


        • #64


          Awesome. looking forward to it.
          Formerly known as "E" on Apolyton

          See me at Civfanatics.com

          Comment


          • #65
            Originally posted by Solver
            Able to compile here and all is fine. Just hit a little snag now, but that's to be fixed soon.

            Solver any luck?
            Formerly known as "E" on Apolyton

            See me at Civfanatics.com

            Comment


            • #66
              IDEA!

              Ranged bombardment = good

              add 2 things to it...

              1- the paradrop has a part of the code that allows a paradrop to "miss" its drop and land its drop in an adjacent tile (as long as they can land there and its vacant)
              USE THIS CODE somehow,... (I haven't looked at it) for the ranged bombardment give it a chance to miss

              2- say, every 1 tile past adjacent, scale the previous chance and add a +20% chance to miss, therefore the max distance for firing is 4 squares away to guarantee a chance of a direct hit


              which gave me an idea for a new unit type...

              remember railway cannons in WW2???
              railroad + explosives = railway cannons
              limit the cannons to movement to railroads ONLY and (for future maglev's too) and drop its max movement to 1 square.
              give them some insane range like 15 tiles, a very powerful shell hell even two shells, and a 20% accuracy at max range.

              this kind of unit could decimate a city from afar, and would require a ranged means of engagement, LIKE BOMBERS!... I never really used bombers much in the origional game, but this unit would give it a reason to.

              and the levithan, give it the same ranged ability, but no limitation on where to move.

              just my .02$
              -----------------------------------------
              I want Master of Magic back :p

              Comment


              • #67
                Solver sent me this. i'm going to dig around unless any coders can double check it first...


                I haven't compiled this... but I'll give you te pointers on what I think has to be done.

                In ArmyData::PerformOrderHere, it enacts the "fire and forget" feauture. I believe that the line 8555 (around that, that's with my changes) has to be changed from
                Code:
                	if (tmp_path->GetMovesRemaining() > 0 && !order_rec->GetIsTeleport() && !order_rec->GetIsTarget(){
                to

                Code:
                	if (tmp_path->GetMovesRemaining() > 0 && !order_rec->GetIsTeleport() && !order_rec->GetIsTarget() && order_rec->GetEventName() != "BombardOrder") {
                Or just createa new function in order_rec like GetIsBombard, which I don't think should matter, but the above way seems easier.

                Likewise, in ArmyData::Bombard, make sure that

                Code:
                		if(!point.IsNextTo(m_pos)) {//rem: this is why you can't bombard from range as in Civ:CTP
                			return ORDER_RESULT_ILLEGAL;
                Is not active. Something like this should work.

                Code:
                if(point == m_pos) {
                		
                		return ORDER_RESULT_ILLEGAL;
                	} else {
                		if (!CanBombard(point)) {
                
                			return ORDER_RESULT_ILLEGAL;
                		}
                		/*
                		if(!point.IsNextTo(m_pos)) {//rem: this is why you can't bombard from range as in Civ:CTP
                			return ORDER_RESULT_ILLEGAL;
                		}*/
                	}

                That's what I have tinkered with, but these ideas are untested, yet they are probably a good foundation for checking out.

                I'll dig up the code and do the changes but I dont have a compiler (but I will test it)
                Formerly known as "E" on Apolyton

                See me at Civfanatics.com

                Comment


                • #68
                  I made solver's recommendedd hanges, can anyone with a compiler make an exe for this? I'll test it
                  Attached Files
                  Formerly known as "E" on Apolyton

                  See me at Civfanatics.com

                  Comment


                  • #69
                    Actually, it turns out to be more complicated than that.

                    It's not that difficult to get an army to bombard from range, provided that it's within it's range of the target. Where it gets hairy is when the army is outside of that range. I have a feeling that it may be necessary to change UnitAstar::FindPath so that it can return a 'ranged path': visualize this as solid lines from the army's position to the point at which it is within bombarding range of the target and then, say, dotted lines from that point to the target. If the army is out of range we then insert a move order to that firing point.

                    Comments greatly appreciated (especially if someone can come up with an easier way of doing this).

                    Comment


                    • #70
                      By increasing bombardment range do you mean being able to bombard
                      further than the tile next to the unit?

                      I apologize for my ignorance.
                      "

                      Comment


                      • #71
                        Yup, that's the way it used to work in CTP1.

                        Comment


                        • #72
                          It's not that difficult to get an army to bombard from range, provided that it's within it's range of the target. Where it gets hairy is when the army is outside of that range. I have a feeling that it may be necessary to change UnitAstar::FindPath so that it can return a 'ranged path': visualize this as solid lines from the army's position to the point at which it is within bombarding range of the target and then, say, dotted lines from that point to the target. If the army is out of range we then insert a move order to that firing point.


                          Or just tell the game not to draw an Astar path if the target is outside of range, returning an order invalid message .
                          Solver, WePlayCiv Co-Administrator
                          Contact: solver-at-weplayciv-dot-com
                          I can kill you whenever I please... but not today. - The Cigarette Smoking Man

                          Comment


                          • #73
                            Where can we add that in the code?





                            Originally posted by Solver
                            It's not that difficult to get an army to bombard from range, provided that it's within it's range of the target. Where it gets hairy is when the army is outside of that range. I have a feeling that it may be necessary to change UnitAstar::FindPath so that it can return a 'ranged path': visualize this as solid lines from the army's position to the point at which it is within bombarding range of the target and then, say, dotted lines from that point to the target. If the army is out of range we then insert a move order to that firing point.


                            Or just tell the game not to draw an Astar path if the target is outside of range, returning an order invalid message .
                            Formerly known as "E" on Apolyton

                            See me at Civfanatics.com

                            Comment


                            • #74
                              I just had a quick look at the changes you made to ArmyData.cpp. Unfortunately, I have been too busy this week to do much coding and compiling. And I am not sure whether I will get around to do anything on CtP2 in the next 2 weeks.

                              The change in Bombard looks OK to me. However, the change in PerformOrderHere is probably not needed. Actually, reinstating the original code may already go a large step towards what you are looking for. Note that the "SnipEnd" for-loop will have removed the last "range" steps of the path before inserting the move order - so you will stop moving when "range" steps from the target, and start the actual bombarding from there. When the path is straight, this is most likely just what you want. When the path is bent (around unpassable or higher move cost tiles), you may want to replace the simple for-loop with something more intelligent, so you will stop at the first step of the path that allows you to bombard the target.

                              Even better would be to make a specialised BombardAStar - as suggested by Peter Triggs - to be used e.g. in the SelectedItem class when the path is computed and you have the bombard order selected.

                              Comment


                              • #75
                                This hasn't been extensively tested but, fingers crossed, so far so good. That is, it seems to work.

                                The first thing I did was to add a function that lets you get the army's min and max bombarding ranges as determined by Units.txt:

                                Code:
                                 #if !defined(ACTIVISION_ORIGINAL)
                                //----------------------------------------------------------------------------
                                //
                                // Name       : ArmyData::GetBombardRange
                                //
                                // Description: Test if this army can bombard. Fill in min_rge and max_rge.
                                //
                                // Parameters : sint32 & min_rge : the min of the bombard ranges of this army's units
                                //            : sint32 & max_rge : the max of the bombard ranges of this army's units
                                //
                                // Globals    : -
                                //				
                                // Returns    : bool
                                //
                                // Remark(s)  : min_rge is not used yet, pft
                                //
                                // Called by  : ArmyData::PerformOrderHere, ArmyData::Bombard
                                //
                                //----------------------------------------------------------------------------
                                bool ArmyData::GetBombardRange(sint32 & min_rge, sint32 & max_rge)
                                {
                                	sint32 i;
                                	min_rge = 99999;
                                	max_rge = 0;
                                
                                    for(i = 0; i < m_nElements; i++) {
                                	const UnitRecord *rec = g_theUnitDB->Get(m_array[i]->GetType());
                                	sint32 rge;
                                        rec->GetBombardRange(rge);
                                	if(rge){
                                            if(rgemax_rge)
                                	        max_rge = rge;
                                            }
                                	}
                                	if(max_rge > 0)
                                	    return true;
                                	
                                	return false;
                                }
                                #endif
                                This is used in Bombard as follows:

                                Code:
                                #if defined(ACTIVISION_ORIGINAL)
                                    if(!point.IsNextTo(m_pos)) {
                                #else
                                    sint32 dist = MapPoint::GetSquaredDistance(m_pos,point);
                                    dist = sqrt(dist);
                                    sint32 min_rge, max_rge;
                                    GetBombardRange(min_rge,max_rge);
                                
                                    if(dist > max_rge) {//the target is out of this army's bombarding range
                                #endif
                                        return ORDER_RESULT_ILLEGAL;
                                    }
                                Like I said above, the hairy bit is where you're ordering an army to bombard but it's outside of it's
                                bombarding range. It's basically just like Fromafar described except that I used the straight line
                                distance between the army and it's target rather than the path length.

                                Code:
                                void ArmyData::PerformOrderHere(const OrderRecord * order_rec, const Path * path)
                                {
                                    Assert(path != NULL);
                                
                                    if (path == NULL)
                                	return ;
                                    if (m_flags & k_CULF_IN_SPACE)
                                	return;
                                    Path *tmp_path = new Path((Path *) path);
                                    MapPoint target_pos;
                                
                                    if (tmp_path->GetMovesRemaining() > 0)
                                    {		
                                	target_pos = tmp_path->GetEnd();
                                    }
                                    else
                                    {		
                                        target_pos = m_pos;
                                    }
                                    if (s_orderDBToEventMap == NULL)
                                	AssociateEventsWithOrdersDB();
                                    Assert(s_orderDBToEventMap != NULL);
                                    sint32 game_event = s_orderDBToEventMap[order_rec->GetIndex()];
                                    sint32 range = 0;
                                    sint32 moves = tmp_path->GetMovesRemaining();
                                    //order_rec: range = 0 (army must be on top of tile) or range = 1 (can execute order from adjacent tile)
                                    if (order_rec->GetRange()) {
                                	order_rec->GetRange(range);
                                	Assert(range <= moves || order_rec->GetTargetPretestAdjacentPosition());            
                                    }
                                
                                #if !defined(ACTIVISION_ORIGINAL)
                                
                                    sint32 min_rge, max_rge=0;
                                    MapPoint move_pos = m_pos;//move_pos will become a position to move to if trying to bombard out of range
                                    Path *move_path = tmp_path;//copy tmp_path
                                    if (strcmp (order_rec->GetEventName(),"BombardOrder") == 0){
                                        if(GetBombardRange(min_rge, max_rge)){
                                            sint32 dist = MapPoint::GetSquaredDistance(m_pos,target_pos);
                                	    dist=sqrt(dist);
                                            if(dist > max_rge){//target is out of range
                                                for(sint32 i=0;iIncDir();			
                                                    tmp_path->GetCurrentPoint(move_pos);
                                                    dist = MapPoint::GetSquaredDistance(move_pos,target_pos);
                                		    dist = sqrt(dist);
                                
                                                    if(dist <= max_rge){ //we're now within range
                                			tmp_path->Start(m_pos);//reset tmp_path
                                			for(sint32 j=1; jSnipEnd();
                                			}
                                			i=moves;//exit the loop and continue
                                		    }
                                		}
                                	    }
                                        }
                                    }
                                    else{
                                #endif		
                                        for (sint32 i = 0; moves > 0 && i < range; i++){
                                	    tmp_path->SnipEnd();
                                	    moves--;
                                	}
                                #if !defined(ACTIVISION_ORIGINAL)
                                    }
                                #endif	
                                    g_gevManager->Pause();
                                    //insert order's game_event here	
                                    if (game_event > 0)	{
                                	if (range > 0 || order_rec->GetIsTeleport() || order_rec->GetIsTarget())//event needs target pos
                                	    {
                                	    	g_gevManager->AddEvent( GEV_INSERT_AfterCurrent, 
                                		static_cast(game_event), 
                                		GEA_Army, Army(m_id), 
                                		GEA_MapPoint, target_pos,
                                		GEA_End);
                                	}
                                        else {
                                		g_gevManager->AddEvent( GEV_INSERT_AfterCurrent, 
                                		static_cast(game_event), 
                                		GEA_Army, Army(m_id), 
                                		GEA_End);
                                	}
                                    }
                                    //insert GEV_MoveOrder here, i.e., move adjacent to target pos or within bombarding range of target pos	
                                    if (tmp_path->GetMovesRemaining() > 0 && !order_rec->GetIsTeleport() && !order_rec->GetIsTarget()) {
                                #if !defined(ACTIVISION_ORIGINAL)
                                        if(max_rge){//max_rge >0 implys BombardOrder and army has bombarding units
                                	    if(move_pos != m_pos){//then first move army to move_pos
                                
                                                g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_MoveOrder, 
                                		    GEA_Army, Army(m_id),
                                		    GEA_Path, move_path,
                                		    GEA_MapPoint, move_pos,
                                		    GEA_Int, (game_event == -1),
                                		    GEA_End);
                                	     }
                                	     //bombard target_pos
                                
                                	     g_gevManager->AddEvent( GEV_INSERT_AfterCurrent, 
                                	         static_cast(game_event), 
                                		 GEA_Army, Army(m_id), 
                                		 GEA_MapPoint, target_pos, 
                                		 GEA_End);
                                
                                	 }
                                	 else{//not a bombard order
                                #endif
                                             g_gevManager->AddEvent(GEV_INSERT_AfterCurrent,
                                	         GEV_MoveOrder, 
                                		 GEA_Army, Army(m_id),			
                                		 GEA_Path, tmp_path,		 
                                		 GEA_MapPoint, target_pos, 
                                		 GEA_Int, (game_event == -1), 
                                		 GEA_End);
                                
                                #if !defined(ACTIVISION_ORIGINAL)
                                	}
                                #endif
                                    }
                                    else {
                                	     delete tmp_path;
                                    }
                                    g_gevManager->AddEvent(GEV_INSERT_AfterCurrent, GEV_ClearOrders,
                                	GEA_Army, Army(m_id),
                                	GEA_End);
                                    g_gevManager->Resume();
                                }

                                Comment

                                Working...
                                X