Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
import tabs.Tab;
|
||||
import tabs.tabbar;
|
||||
import abilities;
|
||||
import hooks;
|
||||
from gui import isGuiHovered;
|
||||
|
||||
import targeting.targeting;
|
||||
from obj_selection import hoveredObject, uiObject, selectedObjects;
|
||||
|
||||
export ObjectTargeting;
|
||||
export AbilityTargetObject;
|
||||
export targetObject;
|
||||
export toggleAbilityTargetObject;
|
||||
|
||||
import Tab@ createGalaxyTab() from "tabs.GalaxyTab";
|
||||
|
||||
class ObjectTargeting {
|
||||
Tab@ returnTo;
|
||||
Sprite icon(spritesheet::ContextIcons, 1);
|
||||
bool allowMultiple = false;
|
||||
bool isTemporary = false;
|
||||
bool drawCrosshair = true;
|
||||
Color validIconColor = colors::Green;
|
||||
Color errorIconColor = colors::Red;
|
||||
vec2i iconSize(40, 40);
|
||||
|
||||
bool valid(Object@ target) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void call(Object@ target) {
|
||||
}
|
||||
|
||||
string message(Object@ target, bool valid) {
|
||||
return target.name;
|
||||
}
|
||||
|
||||
string desc(Object@ target, bool valid) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string emptyMessage() {
|
||||
return "";
|
||||
}
|
||||
|
||||
void hover(Object@ target, const vec2i& mouse) {
|
||||
}
|
||||
|
||||
void draw(Object@ target, bool valid) {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
}
|
||||
};
|
||||
|
||||
class AbilityTargetObject : ObjectTargeting {
|
||||
Ability@ abl;
|
||||
Targets@ targs;
|
||||
|
||||
AbilityTargetObject(Ability@ abl) {
|
||||
@this.abl = abl;
|
||||
@targs = Targets(abl.type.targets);
|
||||
icon = abl.type.icon;
|
||||
}
|
||||
|
||||
bool valid(Object@ target) override {
|
||||
@targs.fill(0).obj = target;
|
||||
return abl.canActivate(targs);
|
||||
}
|
||||
|
||||
void call(Object@ target) override {
|
||||
@targs.fill(0).obj = target;
|
||||
double range = abl.getRange(targs);
|
||||
array<Object@> objects = selectedObjects;
|
||||
if(objects.find(abl.obj) == -1)
|
||||
objects.insertLast(abl.obj);
|
||||
bool playedSound = false;
|
||||
for(uint i = 0, cnt = objects.length; i < cnt; ++i) {
|
||||
Object@ obj = objects[i];
|
||||
if(obj is null || (!obj.isArtifact && !obj.owner.controlled) || !obj.hasAbilities)
|
||||
continue;
|
||||
int ablId = -1;
|
||||
if(obj is abl.obj)
|
||||
ablId = abl.id;
|
||||
else
|
||||
ablId = obj.findAbilityOfType(abl.type.id);
|
||||
if(ablId != -1) {
|
||||
if(obj !is null) {
|
||||
if(obj.hasLeaderAI && range != INFINITY)
|
||||
obj.addAbilityOrder(ablId, target, range, shiftKey);
|
||||
else
|
||||
obj.activateAbility(ablId, target);
|
||||
}
|
||||
else
|
||||
abl.emp.activateAbility(ablId, target);
|
||||
if(abl.type.activateSound !is null && !playedSound) {
|
||||
abl.type.activateSound.play(priority=true);
|
||||
playedSound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string message(Object@ target, bool valid) override {
|
||||
return abl.type.name;
|
||||
}
|
||||
|
||||
string desc(Object@ target, bool valid) {
|
||||
if(!valid) {
|
||||
string err = abl.getTargetError(targs);
|
||||
if(err.length != 0)
|
||||
return err;
|
||||
}
|
||||
return abl.formatCosts(targs);
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectMode : TargetMode {
|
||||
Object@ obj;
|
||||
ObjectTargeting@ targ;
|
||||
|
||||
bool isValidTarget(Object@ obj) override {
|
||||
if(obj is null)
|
||||
return false;
|
||||
if(!targ.valid(obj))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hover(const vec2i& mouse) override {
|
||||
@obj = hoveredObject;
|
||||
if(obj is null)
|
||||
@obj = uiObject;
|
||||
targ.hover(obj, mouse);
|
||||
return isValidTarget(obj);
|
||||
}
|
||||
|
||||
bool click() override {
|
||||
if(obj is null) {
|
||||
if(targ.isTemporary)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if(!targ.valid(obj)) {
|
||||
if(targ.isTemporary) {
|
||||
@obj = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string get_message() override {
|
||||
if(obj is null)
|
||||
return targ.emptyMessage();
|
||||
return targ.message(obj, valid);
|
||||
}
|
||||
|
||||
string get_desc() override {
|
||||
if(obj is null)
|
||||
return "";
|
||||
return targ.desc(obj, valid);
|
||||
}
|
||||
|
||||
Object@ get_target() override {
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectDisplay : TargetVisuals {
|
||||
ObjectTargeting@ targ;
|
||||
|
||||
void draw(TargetMode@ mode) override {
|
||||
if(isGuiHovered() && uiObject is null)
|
||||
return;
|
||||
|
||||
Color color;
|
||||
if(mode.valid)
|
||||
color = Color(0x00ff00ff);
|
||||
else
|
||||
color = Color(0xff3333ff);
|
||||
if(mode.target is null)
|
||||
color = Color(0xaaaaaaff);
|
||||
|
||||
Color iconColor = color;
|
||||
if(mode.target !is null && targ !is null) {
|
||||
if(mode.valid)
|
||||
iconColor = targ.validIconColor;
|
||||
else
|
||||
iconColor = targ.errorIconColor;
|
||||
}
|
||||
|
||||
//Draw the cursor
|
||||
vec2i isize = vec2i(40, 40);
|
||||
Sprite icon = spritesheet::ContextIcons+1;
|
||||
|
||||
if(targ !is null) {
|
||||
icon = targ.icon;
|
||||
isize = targ.iconSize;
|
||||
}
|
||||
icon.draw(recti_area(mousePos-isize/2, isize), iconColor);
|
||||
if(targ is null || targ.drawCrosshair) {
|
||||
drawLine(mousePos-vec2i(isize.x, 0), mousePos+vec2i(isize.x,0), color, 2);
|
||||
drawLine(mousePos-vec2i(0, isize.y), mousePos+vec2i(0,isize.y), color, 2);
|
||||
}
|
||||
|
||||
if(targ !is null)
|
||||
targ.draw(mode.target, mode.valid);
|
||||
|
||||
//Draw the message
|
||||
const Font@ ft = font::DroidSans_11_Bold;
|
||||
string err = mode.desc;
|
||||
if(err.length != 0) {
|
||||
ft.draw(recti_area(mousePos-vec2i(200,isize.y+30), vec2i(400, 20)), mode.message, horizAlign=0.5, color=color, stroke=colors::Black);
|
||||
@ft = font::OpenSans_11_Italic;
|
||||
ft.draw(recti_area(mousePos-vec2i(200,isize.y+5), vec2i(400, 20)), err, horizAlign=0.5, color=color, stroke=colors::Black);
|
||||
}
|
||||
else {
|
||||
ft.draw(recti_area(mousePos-vec2i(200,isize.y+5), vec2i(400, 20)), mode.message, horizAlign=0.5, color=color, stroke=colors::Black);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectCB : TargetCallback {
|
||||
ObjectTargeting@ targ;
|
||||
|
||||
void call(TargetMode@ mode) override {
|
||||
if(targ.isTemporary && mode.target is null) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
if(!mode.isShifted || !shiftKey)
|
||||
clear();
|
||||
targ.call(mode.target);
|
||||
targ.clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
targ.clear();
|
||||
if(targ.returnTo !is null) {
|
||||
if(targ.returnTo is ActiveTab.previous)
|
||||
popTab(ActiveTab);
|
||||
else
|
||||
switchToTab(targ.returnTo);
|
||||
}
|
||||
}
|
||||
|
||||
void cancel(bool wasExplicit) {
|
||||
clear();
|
||||
if(wasExplicit)
|
||||
targ.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
void targetObject(ObjectTargeting@ target, Tab@ returnTo = null, bool gotoTab = true) {
|
||||
ObjectMode targ;
|
||||
ObjectDisplay disp;
|
||||
ObjectCB cb;
|
||||
|
||||
@target.returnTo = returnTo;
|
||||
@targ.targ = target;
|
||||
@disp.targ = target;
|
||||
@cb.targ = target;
|
||||
|
||||
startTargeting(targ, disp, cb);
|
||||
if(target.allowMultiple)
|
||||
targ.autoMultiple = true;
|
||||
|
||||
if(gotoTab) {
|
||||
Tab@ tab = findTab(TC_Galaxy);
|
||||
if(tab !is null) {
|
||||
switchToTab(tab);
|
||||
}
|
||||
else {
|
||||
if(returnTo !is null)
|
||||
browseTab(ActiveTab, createGalaxyTab(), true);
|
||||
else
|
||||
switchToTab(newTab(createGalaxyTab()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void toggleAbilityTargetObject(Ability@ abl) {
|
||||
auto@ om = cast<ObjectMode>(mode);
|
||||
if(om !is null) {
|
||||
auto@ t = cast<AbilityTargetObject>(om.targ);
|
||||
if(t !is null) {
|
||||
if(t.abl.obj is abl.obj && t.abl.id == abl.id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetObject(AbilityTargetObject(abl));
|
||||
}
|
||||
Reference in New Issue
Block a user