openclonk/planet/Objects.ocd/HUD.ocd/Elements.ocd/CrewSelector.ocd/Script.c

455 lines
9.9 KiB
C

/**
HUD Crew Selector
For each crew member, one of these HUD elements exist in the top bar.
It shows the rank, health, breath and magic bars as well as the title
(or portrait) and is clickable. If clicked, the associated crew member
get's selected.
HUD elements are passive, they don't update their status by themselves
but rely on the HUD controller to be notified of any changes.
@authors Newton
*/
#include Library_Bars
local crew, breathbar, magicbar, hotkey;
local energypos, magicpos;
public func BarSpacing() { return -4; }
public func HealthBarHeight() { return 14; }
public func BreathBarHeight() { return 8; }
public func MagicBarHeight() { return 14; }
/*
usage of layers:
-----------------
layer 0 - unused
layer 2 - title
layer 1,3 - background-effects
layer 4,5 - health bar
layer 6,7 - breath bar
layer 8,9 - magic bar
layer 10 - rank
layer 12 - hotkey
*/
/*
The crew selector needs to be notified when
-------------------
...his clonk...
+ changes his energy -> UpdateHealthBar()
+ changes his breath -> UpdateBreathBar()
+ changes his magic energy -> UpdateMagicBar()
+ (temporarily) changes his physical (energy, breath, magic energy) -> see above
+ gains a rank -> UpdateRank()
+ is selected/is deselected as cursor -> UpdateSelectionStatus()
+ changes it's title graphic (either by SetGraphics or by ChangeDef) -> UpdateTitleGraphic()
*/
static const GUI_CS_Base = 0;
static const GUI_CS_Title = 2;
static const GUI_CS_BreathBG = 1;
static const GUI_CS_HealthBG = 3;
static const GUI_CS_HealthBar = 4;
static const GUI_CS_HealthText = 5;
static const GUI_CS_BreathBar = 6;
static const GUI_CS_BreathText = 7;
static const GUI_CS_SpecialBar = 8;
static const GUI_CS_SpecialText = 9;
static const GUI_CS_Rank = 10;
static const GUI_CS_Hotkey = 12;
protected func Construction()
{
_inherited();
breathbar = false;
magicbar = false;
hotkey = false;
energypos = 0;
magicpos = 0;
// parallaxity
this["Parallaxity"] = [0,0];
// visibility
this["Visibility"] = VIS_None;
// health bar
SetBarLayers(GUI_CS_HealthBar,0);
SetBarOffset(0,BarOffset(0),0);
SetBarDimensions(GetDefWidth(),HealthBarHeight(),0);
SetClrModulation(RGB(200,0,0),GUI_CS_HealthText);
}
public func MouseSelection(int plr)
{
if(!crew) return false;
if(plr != GetOwner()) return false;
if(!(crew->GetCrewEnabled())) return false;
// stop previously selected crew
StopSelected();
// set cursor if not disabled etc.
return SetCursor(plr, crew);
}
public func SetCrew(object c)
{
// reset old crew, if there
if(crew)
RemoveEffect("GUIHealthMonitor", crew);
crew = c;
UpdateHealthBar();
UpdateBreathBar();
UpdateMagicBar();
UpdateTitleGraphic();
UpdateRank();
UpdateController();
UpdateSelectionStatus();
UpdateName();
this["Visibility"] = VIS_Owner;
ScheduleCall(this, "AddMonitorEffect", 1);
}
private func AddMonitorEffect()
{
if(!crew)
return;
AddEffect("GUIHealthMonitor", crew, 50, 0, this);
}
public func SetHotkey(int num)
{
if(num < 0 || num > 9)
{
SetGraphics(nil,nil,GUI_CS_Hotkey);
hotkey = false;
return;
}
var kx = 1000 * GetDefWidth()/2 - 10000;
var ky = -1000 * GetDefWidth()/2 + 10000;
hotkey = true;
var name = Format("%d",num);
SetGraphics(name,Icon_Number,GUI_CS_Hotkey,GFXOV_MODE_IngamePicture);
SetObjDrawTransform(300,0,kx,0,300,ky, GUI_CS_Hotkey);
SetClrModulation(HSL(0,0,180),GUI_CS_Hotkey);
}
public func CrewGone()
{
RemoveObject();
}
private func UpdateTexts()
{
CustomMessage("",this,crew->GetOwner());
if(crew->GetEnergy() > 0)
CustomMessage(Format("@<c dddd00>%d</c>",crew->GetEnergy()), this, crew->GetOwner(), energypos, GetDefHeight()/2 + BarOffset(0) + 14, nil, nil, nil, MSG_Multiple);
/* if(crew->GetMagicEnergy() > 0)
CustomMessage(Format("@<c 1188cc>%d</c>",crew->GetMagicEnergy()), this, crew->GetOwner(), magicpos, GetDefHeight()/2 + BarOffset(1) + 14, nil, nil, nil, MSG_Multiple);*/
CustomMessage(Format("@%s",crew->GetName()), this, crew->GetOwner(), 0, GetDefHeight(), nil, nil, nil, MSG_Multiple);
}
public func UpdateController()
{
if(!crew) return;
// visibility
SetOwner(crew->GetController());
// name
var fullname = Format("%s %s",crew->GetObjCoreRankName(),crew->GetName());
SetName(crew->GetName());
this.Tooltip = Format("$TxtSelect$",fullname);
}
public func UpdateSelectionStatus()
{
if(!crew) return;
if(!hotkey) return;
if(crew == GetCursor(crew->GetOwner()))
{
SetObjDrawTransform(1100,0,0,0,1100,0, GUI_CS_Title);
}
else
{
SetObjDrawTransform(800,0,0,0,800,0, GUI_CS_Title);
}
}
public func UpdateRank()
{
if(!crew) return;
var rankx = -1000 * GetDefWidth()/2 + 12000;
var ranky = -13000;
SetGraphics(nil,0,GUI_CS_Rank,GFXOV_MODE_Rank,nil,0,crew);
SetObjDrawTransform(1000,0,rankx,0,1000,ranky, GUI_CS_Rank);
}
public func UpdateTitleGraphic()
{
if(!crew) return;
//SetGraphics(nil,crew->GetID(),1,GFXOV_MODE_Object,nil,nil,crew);
SetGraphics(nil,crew->GetID(),GUI_CS_Title,GFXOV_MODE_ObjectPicture, nil, 0, crew);
// doesn't work:
//SetColorDw(crew->GetColorDw());
}
public func UpdateHealthBar()
{
if(!crew) return;
var phys = crew->GetMaxEnergy();
var promille;
if(phys == 0) promille = 0;
else promille = 1000 * crew->GetEnergy() / phys;
energypos = -GetDefWidth()/2*(1000-promille)/1000;
SetBarProgress(promille,0);
UpdateTexts();
}
public func UpdateBreathBar()
{
if(!crew) return;
var phys = crew->GetMaxBreath();
var promille;
if(phys == 0) promille = 0;
else promille = 1000 * crew->GetBreath() / phys;
// remove breath bar if full breath
if(promille == 1000)
{
if(breathbar)
RemoveBreathBar();
}
// add breath bar if there is none
else
{
if(!breathbar)
AddBreathBar();
SetBarProgress(promille,1);
var clr = GetAverageTextureColor(crew->GetTexture(0,0));
SetClrModulation(clr, GUI_CS_BreathBG);
//SetClrModulation(255-(1000-promille)*76/1000), GUI_CS_BreathBG);
}
}
public func UpdateMagicBar()
{
if(!crew) return;
var phys = 0;
var promille = 0;
//if(phys != 0) promille = 1000 * crew->GetMagicEnergy() / (phys / 1000);
magicpos = -GetDefWidth()/2*(1000-promille)/1000;
// remove magic bar if no physical magic!
if(phys == 0)
{
if(magicbar)
RemoveMagicBar();
}
// add magic bar if there is none
else
{
if(!magicbar)
AddMagicBar();
SetBarProgress(promille,2);
}
UpdateTexts();
}
private func UpdateName()
{
UpdateTexts();
}
private func BarOffset(int num)
{
var offset = GetDefHeight()/2 + HealthBarHeight()/2 + num * BarSpacing();
if(num > 0) offset += HealthBarHeight();
if(num > 1) offset += MagicBarHeight();
return offset;
}
private func AddBreathBar()
{
var num = 1;
if(magicbar) num = 2;
// breath bar
SetBarLayers(GUI_CS_BreathBar,1);
SetBarOffset(0,BarOffset(num),1);
SetBarDimensions(GetDefWidth(),BreathBarHeight(),1);
SetClrModulation(RGB(0,200,200),GUI_CS_BreathText);
breathbar = true;
// also enable background-coloring
SetGraphics("Background", GUI_CrewSelector, GUI_CS_BreathBG, GFXOV_MODE_Base);
}
private func RemoveBreathBar()
{
RemoveBarLayers(GUI_CS_BreathBar);
SetGraphics(nil, nil, GUI_CS_BreathBG);
breathbar = false;
// update position of magic bar (if any)
if(magicbar)
SetBarOffset(0,BarOffset(1),2);
}
private func AddMagicBar()
{
SetBarLayers(GUI_CS_SpecialBar,2);
SetBarOffset(0,BarOffset(1),2);
SetBarDimensions(GetDefWidth(),MagicBarHeight(),2);
SetClrModulation(RGB(0,0,200),GUI_CS_SpecialText);
magicbar = true;
// update position of breath bar (if any)
if(breathbar)
SetBarOffset(0,BarOffset(2),1);
}
private func RemoveMagicBar()
{
RemoveBarLayers(GUI_CS_SpecialBar);
magicbar = false;
}
// highlight
public func OnMouseOver(int plr)
{
if(GetOwner() != plr)
return nil;
SetGraphics("Focussed", GUI_CrewSelector);
}
public func OnMouseOut(int plr)
{
if(GetOwner() != plr)
return nil;
SetGraphics(nil, nil);
}
public func FxGUIHealthMonitorDamage(object target, proplist effect, num damage, int cause)
{
var change = Abs(damage)/(target->GetMaxEnergy()*10);
// for really small changes, like fire or higher precision DoEnergy
if(change == 0)
change = 3;
//if(!GetEffect("GUIHealthMonitorWorker", this))
if(!effect.worker)
{
effect.worker = AddEffect("GUIHealthMonitorWorker", target, 150, 4, this);
effect.worker.intensity = change+20;
}
else
effect.worker.intensity += change;
effect.worker.intensity = BoundBy(effect.worker.intensity, 0, 80);
// heal
if(damage > 0)
effect.worker.type = 1;
// damage
else
effect.worker.type = 0;
// fire
if(cause == FX_Call_DmgFire || cause == FX_Call_EngFire)
effect.worker.type = 2;
return damage;
}
public func FxGUIHealthMonitorWorkerStart(object target, proplist effect, bool tmp)
{
if(tmp) return;
SetGraphics("Hurt", GUI_CrewSelector, GUI_CS_HealthBG, GFXOV_MODE_Base, nil, GFX_BLIT_Additive);
EffectCall(target, effect, "Timer");
}
public func FxGUIHealthMonitorWorkerTimer(object target, proplist effect, int time)
{
// do graphical effect
var a = BoundBy(effect.intensity*7, 20, 255);
// damage
if(effect.type == 0)
{
var r = Min(200 + effect.intensity, 255);
SetClrModulation(RGBa(r,0,0,a), GUI_CS_HealthBG);
}
// heal
else if(effect.type == 1)
{
var g = Min(100 + effect.intensity, 255);
a = Min(a+100, 255);
SetClrModulation(RGBa(50,g,50,a), GUI_CS_HealthBG);
}
// fire!
else if(effect.type == 2)
{
var r = Min(150 + effect.intensity, 255);
var g = Min(effect.intensity, 100);
a = Min(a+100, 255);
SetClrModulation(RGBa(r,g,0,a), GUI_CS_HealthBG);
}
// not set yet? might happen at the start sometimes. we just hide in that case.
else
SetClrModulation(RGBa(0,0,0,0), GUI_CS_HealthBG);
var dec = 3;
// fade faster if huge numbers
if(effect.intensity > 60)
dec += 2;
effect.intensity = effect.intensity-dec;
// we're done, remove effect
if(effect.intensity <= 0)
return -1;
}
public func FxGUIHealthMonitorWorkerStop(object target, proplist effect, int reason, bool tmp)
{
if(tmp) return;
SetGraphics(nil, nil, GUI_CS_HealthBG);
}