diff --git a/binaries/data/mods/official/art/textures/skies/day1/back.dds b/binaries/data/mods/official/art/textures/skies/day1/back.dds
new file mode 100644
index 0000000000..3b81c6acba
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/back.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c9eec24ba092990cb4a4c037133c28e58cb93f6c25f27d11c6c1f86d8154aba5
+size 262272
diff --git a/binaries/data/mods/official/art/textures/skies/day1/bottom.dds b/binaries/data/mods/official/art/textures/skies/day1/bottom.dds
new file mode 100644
index 0000000000..9ed88eba28
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/bottom.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dd7c7723c06eff72ac6fc81f2b0a8f3560ac68d72f83962e2ba2bcbfa71a7138
+size 262272
diff --git a/binaries/data/mods/official/art/textures/skies/day1/front.dds b/binaries/data/mods/official/art/textures/skies/day1/front.dds
new file mode 100644
index 0000000000..6b524435c2
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/front.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:188cb207008478eaeb3800e105581c954524bcac7e0772f54976fbb45e64978f
+size 262272
diff --git a/binaries/data/mods/official/art/textures/skies/day1/left.dds b/binaries/data/mods/official/art/textures/skies/day1/left.dds
new file mode 100644
index 0000000000..d5b0999be3
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/left.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:427b224275e2c3f5e3571d7ba13093ed9e3642eefaf39e2c18917db0e07f5ca2
+size 262272
diff --git a/binaries/data/mods/official/art/textures/skies/day1/right.dds b/binaries/data/mods/official/art/textures/skies/day1/right.dds
new file mode 100644
index 0000000000..5800f4bab9
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/right.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2b712370bf15609d6d344ce6f44805a71f13874cf7746e8530ee4efae4bb1772
+size 262272
diff --git a/binaries/data/mods/official/art/textures/skies/day1/top.dds b/binaries/data/mods/official/art/textures/skies/day1/top.dds
new file mode 100644
index 0000000000..0de761e500
--- /dev/null
+++ b/binaries/data/mods/official/art/textures/skies/day1/top.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bf5d388552b1f7b165c1f073c1ed64d9460e1b02615a4cec2020858eb6550b71
+size 262272
diff --git a/binaries/data/mods/official/entities/template_entity_full.xml b/binaries/data/mods/official/entities/template_entity_full.xml
index 9c01a7d8d6..e1be69ad71 100644
--- a/binaries/data/mods/official/entities/template_entity_full.xml
+++ b/binaries/data/mods/official/entities/template_entity_full.xml
@@ -9,9 +9,9 @@
- 2
- 1
- 3
+ 15
+ 10
+ 5
diff --git a/binaries/data/mods/official/entities/template_entity_script.js b/binaries/data/mods/official/entities/template_entity_script.js
index 6dadb7d086..ec7399321d 100644
--- a/binaries/data/mods/official/entities/template_entity_script.js
+++ b/binaries/data/mods/official/entities/template_entity_script.js
@@ -21,6 +21,7 @@ const ACTION_GATHER = 2;
const ACTION_HEAL = 3;
const ACTION_ATTACK_RANGED = 4;
const ACTION_BUILD = 5;
+const ACTION_REPAIR = 6;
const PRODUCTION_TRAIN = 1;
const PRODUCTION_RESEARCH = 2;
@@ -36,7 +37,7 @@ function entityInit()
// If this is a foundation, initialize traits from the building we're converting into
if( this.building && this.building != "" )
{
- var building = getEntityTemplate( this.building );
+ var building = getEntityTemplate( this.building, this.player );
this.traits.id.generic = building.traits.id.generic;
this.traits.id.specific = building.traits.id.specific;
this.traits.id.civ = building.traits.id.civ;
@@ -187,6 +188,10 @@ function entityInit()
{
this.setActionParams( ACTION_BUILD, 0.0, 2.0, this.actions.build.speed, "build" );
}
+ if( this.actions.repair )
+ {
+ this.setActionParams( ACTION_REPAIR, 0.0, 2.0, this.actions.repair.speed, "build" );
+ }
}
// Attach functions to ourselves
@@ -196,6 +201,7 @@ function entityInit()
this.performGather = performGather;
this.performHeal = performHeal;
this.performBuild = performBuild;
+ this.performRepair = performRepair;
this.damage = damage;
this.entityComplete = entityComplete;
this.GotoInRange = GotoInRange;
@@ -293,22 +299,32 @@ function attachAuras()
if( this.traits.auras.courage )
{
a = this.traits.auras.courage;
- this.addAura ( "courage", a.radius, new DamageModifyAura( this, true, a.bonus ) );
+ this.addAura ( "courage", a.radius, 0, new DamageModifyAura( this, true, a.bonus ) );
}
- if( this.traits.auras.fear )
+ if( this.traits.auras.fear )
{
a = this.traits.auras.fear;
- this.addAura ( "fear", a.radius, new DamageModifyAura( this, false, -a.bonus ) );
+ this.addAura ( "fear", a.radius, 0, new DamageModifyAura( this, false, -a.bonus ) );
}
- if( this.traits.auras.infidelity )
+ if( this.traits.auras.infidelity )
{
a = this.traits.auras.infidelity;
- this.addAura ( "infidelity", a.radius, new InfidelityAura( this, a.time ) );
+ this.addAura ( "infidelity", a.radius, 0, new InfidelityAura( this, a.time ) );
}
- if( this.traits.auras.dropsite )
+ if( this.traits.auras.dropsite )
{
a = this.traits.auras.dropsite;
- this.addAura ( "dropsite", a.radius, new DropsiteAura( this, a.types ) );
+ this.addAura ( "dropsite", a.radius, 0, new DropsiteAura( this, a.types ) );
+ }
+ if( this.traits.auras.heal )
+ {
+ a = this.traits.auras.heal;
+ this.addAura ( "heal", a.radius, a.speed, new HealAura( this ) );
+ }
+ if( this.traits.auras.trample )
+ {
+ a = this.traits.auras.trample;
+ this.addAura ( "trample", a.radius, a.speed, new TrampleAura( this ) );
}
}
}
@@ -324,7 +340,7 @@ function foundationDestroyed( evt )
var bp = this.build_points;
var fractionToReturn = (bp.max - bp.curr) / bp.max;
- var resources = getEntityTemplate( this.building ).traits.creation.resource;
+ var resources = getEntityTemplate( this.building, this.player ).traits.creation.resource;
for( r in resources )
{
amount = parseInt( fractionToReturn * parseInt(resources[r]) );
@@ -344,24 +360,31 @@ function performAttack( evt )
// Attack logic.
var dmg = new DamageType();
- var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
if ( this.getRunState() )
{
console.write("" + this + " doing a charge attack!");
- dmg.crush = parseInt(this.actions.attack.charge.damage * this.actions.attack.charge.crush);
- dmg.hack = parseInt(this.actions.attack.charge.damage * this.actions.attack.charge.hack);
- dmg.pierce = parseInt(this.actions.attack.charge.damage * this.actions.attack.charge.pierce);
+ var a = this.actions.attack.charge;
+ dmg.crush = parseInt(a.damage * a.crush);
+ dmg.hack = parseInt(a.damage * a.hack);
+ dmg.pierce = parseInt(a.damage * a.pierce);
this.setRun( false );
}
else
{
- dmg.crush = parseInt(this.actions.attack.melee.damage * this.actions.attack.melee.crush);
- dmg.hack = parseInt(this.actions.attack.melee.damage * this.actions.attack.melee.hack);
- dmg.pierce = parseInt(this.actions.attack.melee.damage * this.actions.attack.melee.pierce);
+ var a = this.actions.attack.melee;
+ dmg.crush = parseInt(a.damage * a.crush);
+ dmg.hack = parseInt(a.damage * a.hack);
+ dmg.pierce = parseInt(a.damage * a.pierce);
+ }
+
+ // Add flank bonus
+ if(evt.target.traits.flank_penalty)
+ {
+ var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
+ dmg.crush += dmg.crush * flank;
+ dmg.hack += dmg.hack * flank;
+ dmg.pierce += dmg.pierce * flank;
}
- dmg.crush += dmg.crush * flank;
- dmg.hack += dmg.hack * flank;
- dmg.pierce += dmg.pierce * flank;
evt.target.damage( dmg, this );
@@ -375,14 +398,19 @@ function performAttackRanged( evt )
// Create a projectile from us, to the target, that will do some damage when it hits them.
dmg = new DamageType();
- dmg.crush = parseInt(this.actions.attack.ranged.damage * this.actions.attack.ranged.crush);
- dmg.hack = parseInt(this.actions.attack.ranged.damage * this.actions.attack.ranged.hack);
- dmg.pierce = parseInt(this.actions.attack.ranged.damage * this.actions.attack.ranged.pierce);
+ var a = this.actions.attack.ranged;
+ dmg.crush = parseInt(a.damage * a.crush);
+ dmg.hack = parseInt(a.damage * a.hack);
+ dmg.pierce = parseInt(a.damage * a.pierce);
- var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
- dmg.crush += dmg.crush * flank;
- dmg.hack += dmg.hack * flank;
- dmg.pierce += dmg.pierce * flank;
+ // Add flank bonus
+ if(evt.target.traits.flank_penalty)
+ {
+ var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
+ dmg.crush += dmg.crush * flank;
+ dmg.hack += dmg.hack * flank;
+ dmg.pierce += dmg.pierce * flank;
+ }
// The parameters for Projectile are:
// 1 - The actor to use as the projectile. There are two ways of specifying this:
@@ -544,6 +572,12 @@ function performHeal( evt )
function performBuild( evt )
{
+ if( !canBuild( this, evt.target ) )
+ {
+ evt.preventDefault();
+ return;
+ }
+
var t = evt.target;
var b = this.actions.build;
var bp = t.build_points;
@@ -558,7 +592,7 @@ function performBuild( evt )
// We've finished building this object; convert the foundation to a building
if( t.building != "" ) // Might be false if another unit finished building the thing during our last anim cycle
{
- t.template = getEntityTemplate( t.building );
+ t.template = getEntityTemplate( t.building, t.player );
t.building = "";
t.attachAuras();
@@ -572,6 +606,48 @@ function performBuild( evt )
// ====================================================================
+function performRepair( evt )
+{
+ if( !canRepair( this, evt.target ) )
+ {
+ evt.preventDefault();
+ return;
+ }
+
+ var t = evt.target;
+ var b = this.actions.build;
+ var hp = t.traits.health;
+
+ // Find the fraction of max health to repair by; this should be one build tick (i.e. longer for buildings with
+ // longer creation time) but also not so much that it causes the unit to have more than max HP
+ var fraction = Math.min(
+ parseFloat( b.rate ) / t.traits.creation.time,
+ ( hp.max - hp.curr ) / hp.max
+ );
+ console.write("Repair fraction is " + fraction);
+
+ // Check if we can afford to repair
+ var resources = t.traits.creation.resource;
+ for( r in resources )
+ {
+ amount = parseInt( fraction * parseInt(resources[r]) );
+ getGUIGlobal().deductResources( r.toString(), amount );
+ }
+
+ // Heal the building
+ hp.curr = Math.min( hp.max, hp.curr + fraction * hp.max );
+
+ // Deduct the resources
+ var resources = t.traits.creation.resource;
+ for( r in resources )
+ {
+ amount = parseInt( fraction * parseInt(resources[r]) );
+ getGUIGlobal().deductResources( r.toString(), amount );
+ }
+}
+
+// ====================================================================
+
function damage( dmg, inflictor )
{
if(!this.traits.armour) return; // corpses have no armour, everything else should
@@ -636,7 +712,7 @@ function damage( dmg, inflictor )
inflictor.traits.id.icon_cell++;
// Transmogrify him into his next rank.
- inflictor.template = getEntityTemplate(inflictor.traits.promotion.newentity, inflictor.player);
+ inflictor.template = getEntityTemplate( inflictor.traits.promotion.newentity, inflictor.player );
}
}
break;
@@ -706,6 +782,8 @@ function entityEventGeneric( evt )
this.performAttackRanged( evt ); break;
case ACTION_BUILD:
this.performBuild( evt ); break;
+ case ACTION_REPAIR:
+ this.performRepair( evt ); break;
default:
console.write( "Unknown generic action: " + evt.action );
@@ -880,6 +958,17 @@ function entityEventTargetChanged( evt )
evt.secondaryAction = ACTION_BUILD;
evt.secondaryCursor = "action-build";
}
+
+ if ( canRepair( this, evt.target ) )
+ {
+ evt.defaultOrder = NMT_Generic;
+ evt.defaultAction = ACTION_REPAIR;
+ evt.defaultCursor = "action-build";
+
+ evt.secondaryOrder = NMT_Generic;
+ evt.secondaryAction = ACTION_REPAIR;
+ evt.secondaryCursor = "action-build";
+ }
}
@@ -988,6 +1077,16 @@ function entityEventPrepareOrder( evt )
evt.notifyType = NOTIFY_NONE;
this.forceCheckListeners( NOTIFY_ORDER_CHANGE, this );
break;
+
+ case ACTION_REPAIR:
+ if ( !this.actions.repair )
+ {
+ evt.preventDefault();
+ return;
+ }
+ evt.notifyType = NOTIFY_NONE;
+ this.forceCheckListeners( NOTIFY_ORDER_CHANGE, this );
+ break;
}
break;
@@ -1018,7 +1117,7 @@ function entityStartProduction( evt )
if(evt.productionType == PRODUCTION_TRAIN)
{
- var template = getEntityTemplate( evt.name );
+ var template = getEntityTemplate( evt.name, this.player );
var result = entityCheckQueueReq( this, template );
if (result == true) // If the entry meets requirements to be added to the queue (eg sufficient resources)
@@ -1043,7 +1142,7 @@ function entityStartProduction( evt )
}
// Set the amount of time it will take to complete production of the production object.
- evt.time = getEntityTemplate(evt.name).traits.creation.time;
+ evt.time = getEntityTemplate( evt.name, this.player ).traits.creation.time;
}
else
{
@@ -1065,7 +1164,7 @@ function entityCancelProduction( evt )
if(evt.productionType == PRODUCTION_TRAIN)
{
// Give back all the resources spent on this entry.
- var template = getEntityTemplate( evt.name );
+ var template = getEntityTemplate( evt.name, this.player );
var pool = template.traits.creation.resource;
for ( resource in pool )
{
@@ -1092,7 +1191,7 @@ function entityFinishProduction( evt )
if(evt.productionType == PRODUCTION_TRAIN)
{
- var template = getEntityTemplate(evt.name);
+ var template = getEntityTemplate( evt.name, this.player );
// Code to find a free space around an object is tedious and slow, so
// I wrote it in C. Takes the template object so it can determine how
@@ -1220,7 +1319,7 @@ function entityCreateComplete()
function attemptAddToBuildQueue( entity, create_tag, tab, list )
{
- template = getEntityTemplate( create_tag );
+ template = getEntityTemplate( create_tag, entity.player );
result = entityCheckQueueReq( entity, template );
if (result == true) // If the entry meets requirements to be added to the queue (eg sufficient resources)
@@ -1342,6 +1441,19 @@ function canBuild( source, target )
// ====================================================================
+function canRepair( source, target )
+{
+ // Checks whether we're allowed to gather from a target entity (this involves looking at both the type and subtype).
+ if( !source.actions )
+ return false;
+ r = source.actions.repair;
+ return( r && target.traits.health.repairable && target.player.id == source.player.id
+ && target.traits.health.curr < target.traits.health.max
+ && target.building == "" );
+}
+
+// ====================================================================
+
function DamageType()
{
this.typeless = 0.0;
@@ -1524,6 +1636,75 @@ function InfidelityAura( source, time )
}
// ====================================================================
+
+function HealAura( source )
+{
+ // Defines the effects of the Heal aura. Slowly heals nearby allies over time.
+
+ this.source = source;
+
+ this.affects = function( e )
+ {
+ return ( e.player.id == this.source.player.id && e.traits.health
+ && e.traits.health.healable
+ && e.traits.health.curr < e.traits.health.max );
+ }
+
+ this.onTick = function( e )
+ {
+ if( this.affects( e ) )
+ {
+ var hp = e.traits.health;
+ var rate = this.source.traits.auras.heal.rate;
+ hp.curr = Math.min( hp.max, hp.curr + rate );
+ }
+ };
+}
+
+// ====================================================================
+
+function TrampleAura( source )
+{
+ // Defines the effects of the Trample aura. Damages nearby enemies over time if the unit is charging or has recently charged.
+
+ this.source = source;
+
+ this.affects = function( e )
+ {
+ // Check if the target is an enemy foot unit with health and if we were running in the last 3 seconds
+ var a = this.source.traits.auras.trample;
+ return ( e.player.id != this.source.player.id && e.traits.health && e.hasClass("Foot")
+ && (getGameTime() - this.source.last_run_time < a.duration) );
+ }
+
+ this.onTick = function( e )
+ {
+ if( this.affects( e ) )
+ {
+ // Set up the damage object
+ var dmg = new DamageType();
+ var a = this.source.traits.auras.trample;
+ dmg.crush = parseInt(a.damage * a.crush);
+ dmg.hack = parseInt(a.damage * a.hack);
+ dmg.pierce = parseInt(a.damage * a.pierce);
+
+ // Add flank bonus
+ if(e.traits.flank_penalty)
+ {
+ var flank = (e.getAttackDirections()-1)*e.traits.flank_penalty.value;
+ dmg.crush += dmg.crush * flank;
+ dmg.hack += dmg.hack * flank;
+ dmg.pierce += dmg.pierce * flank;
+ }
+
+ // Perform the damage
+ e.damage( dmg, this.source );
+ }
+ };
+}
+
+// ====================================================================
+
function GotoInRange( x, y, run )
{
if ( !this.actions || !this.actions.move )
@@ -1534,7 +1715,9 @@ function GotoInRange( x, y, run )
else
this.order( ORDER_GOTO, x, y - this.actions.escort.distance, true);
}
+
//=====================================================================
+
function entityEventFormation( evt )
{
if ( evt.formationEvent == FORMATION_ENTER )
diff --git a/binaries/data/mods/official/entities/template_structure.xml b/binaries/data/mods/official/entities/template_structure.xml
index 2705492bf8..b4fd5c469e 100644
--- a/binaries/data/mods/official/entities/template_structure.xml
+++ b/binaries/data/mods/official/entities/template_structure.xml
@@ -17,14 +17,23 @@
+
+
+
+ 0
+ 100
+ 50
+
+
+
12.0
+
9
-
diff --git a/binaries/data/mods/official/entities/template_structure_civic_temple.xml b/binaries/data/mods/official/entities/template_structure_civic_temple.xml
index 904ec0a5c9..860a36cd60 100644
--- a/binaries/data/mods/official/entities/template_structure_civic_temple.xml
+++ b/binaries/data/mods/official/entities/template_structure_civic_temple.xml
@@ -27,6 +27,14 @@
8.0
+
+
+ 30
+ 5
+ 2000
+
+
+
600
diff --git a/binaries/data/mods/official/entities/template_unit.xml b/binaries/data/mods/official/entities/template_unit.xml
index 6153f0479c..6d4ffda78c 100644
--- a/binaries/data/mods/official/entities/template_unit.xml
+++ b/binaries/data/mods/official/entities/template_unit.xml
@@ -50,7 +50,7 @@
100
5.0
20
-
+
@@ -83,7 +83,7 @@
15.0
50.0
- 10.0
+ 0.0
10.0
5.0
diff --git a/binaries/data/mods/official/entities/template_unit_cavalry.xml b/binaries/data/mods/official/entities/template_unit_cavalry.xml
index 713cbfc69d..b33c77f0c9 100644
--- a/binaries/data/mods/official/entities/template_unit_cavalry.xml
+++ b/binaries/data/mods/official/entities/template_unit_cavalry.xml
@@ -42,17 +42,6 @@
900
-
-
-
- 1
- 50
- 0
- 0.9
- 0.1
-
-
-
@@ -78,7 +67,7 @@
30.0
- 100.0
+ 150.0
10.0
diff --git a/binaries/data/mods/official/entities/template_unit_cavalry_melee.xml b/binaries/data/mods/official/entities/template_unit_cavalry_melee.xml
index dd67eae33c..a61b89780c 100644
--- a/binaries/data/mods/official/entities/template_unit_cavalry_melee.xml
+++ b/binaries/data/mods/official/entities/template_unit_cavalry_melee.xml
@@ -12,6 +12,18 @@
+
+
+ 10
+ 1000
+ 3
+ 20.0
+ 0.0
+ 0.5
+ 0.5
+
+
+
diff --git a/binaries/data/mods/official/entities/template_unit_infantry.xml b/binaries/data/mods/official/entities/template_unit_infantry.xml
index ad84795194..e1bc5ed807 100644
--- a/binaries/data/mods/official/entities/template_unit_infantry.xml
+++ b/binaries/data/mods/official/entities/template_unit_infantry.xml
@@ -87,7 +87,10 @@
-
+
+ 1.0
+ 1000
+
1.0
diff --git a/binaries/data/mods/official/entities/template_unit_support_female_citizen.xml b/binaries/data/mods/official/entities/template_unit_support_female_citizen.xml
index 326d4b50e3..056d57e0a4 100644
--- a/binaries/data/mods/official/entities/template_unit_support_female_citizen.xml
+++ b/binaries/data/mods/official/entities/template_unit_support_female_citizen.xml
@@ -53,7 +53,10 @@
3000
-
+
+ 0.5
+ 1000
+