Inactive Potions

B!0HAX

Member
Contributor
World
Cervator edit: Header added, moved to Incubator Modules, quite dated by now
Skaldarnar edit: Changed Scope to Mod, opened for new curator.

Name: Status Effects and Potions
Summary: System to apply status effects to the player (and others) mainly through the use of potions
Scope: Mod
Current Goal: Final polish of initial potions, more potions, going beyond potions?
Phase: Implementation
Curator: Awaits new curator! (old curator: B!0HAX)
Related: #242, #262

StatusEffectComponent: Data for handling the different Effects.
·EffectType (enum) : HealthBoost, SpeedBoost, Poisoned, Fatigued...
·EffectDuration...
·EffectIcon (for making a buff/de·buff screen that shows current active stat. effects)

StatusAffectorSystem: Effect Specifications : What it does when the effect is applied.
Code:
switch(effect.type)
case SpeedBoost:
[here call the components that is in charge of the effect]
charactermovementcomponent.runSpeed = xx;
statuseffectcomponent.effectDuration = xx;
"...".effectIcon = "SpeedBoost";
[call a guimanager new UIBuffScreen to add the newly applied bufficon while the timer is counting down.]
["Poisoned" status would be an icon that uses the UIDebuffScreen for example]
break;
[...]
DrinkPotionAction [EventHandler] : For the actual testing of a buff Im using a speedpotion.prefab that carries (potion component) the info that it is a cerulean (light blue) color and inside this eventhanlder the cerulean potions call the speed potions effect.
In this case example:
Code:
switch(potion.type)
case Cerulean:
[Call the statusaffector with the specific effect we want]
call speed effect > statusaffectorsystem.SpeedBoost
//Give an empty vial, destroy empty vial if inventory is full...
[...]
break;
[...]
Currently I do all this from the DrinkPotionAction, but wanting to expand the effects to make them have a "timer" and maybe a place in the screen where it shows an icon if its active... I have thought of it being designed in this way, there will be many ways of doing this... lets see what you guys think about this layout.
 
Last edited by a moderator:

B!0HAX

Member
Contributor
World
Status Effects

This will be the approach for a potion calling its effects (example: speed boost)
For this example StatusEffectComponent = SpeedBoostComponent (other example Poisoned = PoisonedComponent)
Code:
SpeedPotion.prefab -> DrinkPotionAction -[PotionComponent.type.black]-> SpeedBoostEvent* 
*SpeedBoostEvent -[StatusEffectComponent]-> StatusAffectorSystem --> LocalPlayer*
*LocalPlayer's [StatusEffectComponent]
The DrinkPotionAction upon receiving that a black potion is consumed sends:
event.getInstigator().send(new BoostSpeedEvent());

The BoostSpeedEvent returns to the StatusAffectorSystem,
picking up something like : "hey speedBoost is on now!"

StatusAffectorSystem then applies the effect to the player and updates based on the EffectsComponent.EffectDuration
(for speedBoost : SpeedBoostComponent.SpeedBoostDuration)

For the Effects Duration : update (float delta)
> 1. Go over every entity with a StatusEffectComponent
> 2. subtract delta from the effect's EffectDuration
> 3. If EffectDuration <= 0, remove the effect
 

B!0HAX

Member
Contributor
World
Status Effects [CRASH ISSUE]

DrinkPotionAction : for when the player chugs a speed potion, this line call the effects
Code:
event.getInstigator().send(new BoostSpeedEvent());
BoostSpeedEvent : This is what connects drinking a potion with Speed Boosting effect of the Status Affector.
Code:
public class BoostSpeedEvent extends AbstractEvent {
    private EntityRef instigator;

    public BoostSpeedEvent() {
        this.instigator = EntityRef.NULL;
    }

    public BoostSpeedEvent(EntityRef instigator) {
        this.instigator = instigator;
    }

    public EntityRef getInstigator() {
        return instigator;
    }
StatusAffectorSystem :
Code:
//This would be the specific effect of the "Speed Boost" property (potion/spell)
    @ReceiveEvent(components = {SpeedBoostComponent.class})
    public void onActivate(ActivateEvent event, BoostSpeedEvent boostevent, EntityRef entity, SpeedBoostComponent speedEffect) {
        CharacterMovementComponent charmov = event.getTarget().getComponent(CharacterMovementComponent.class);
        boostevent.getInstigator().exists();
        speedEffect.speedBoostDuration = 10f;
        charmov.runFactor = 8.0f;
        event.getTarget().saveComponent(charmov);
    }
    /*
     * The Effects Duration Countdown "timer"
     */
    public void update(float delta) {
         update(speedEffect.speedBoostDuration - delta);
        if (speedEffect.speedBoostDuration <= 0) {   //Returns to normal run speed.
            charmov.runFactor = 1.5f;
            event.getTarget().saveComponent(charmov);
        }
Slowly building the concept up...
Currently the game crashes when I try to create a new world.
When I looked at the console :
[...]
INFO: Registering event handler org.terasology.componentSystem.action.DrinkPotionAction
May 9, 2012 7:18:04 PM org.terasology.entitySystem.pojo.PojoEventSystem registerEventHandler
WARNING: Invalid event handler method: onActivate
May 9, 2012 7:18:04 PM org.terasology.entitySystem.pojo.PojoEventSystem registerEventHandler
INFO: Registering event handler org.terasology.componentSystem.common.StatusAffectorSystem
May 9, 2012 7:18:04 PM org.terasology.entitySystem.pojo.PojoEventSystem registerEventHandler
WARNING: Invalid event handler method: onActivate
[...]
SEVERE: Uncaught Exception


Help is appreciated. :]
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Concept design seems solid to me :)

Few notes:
* Are you sure you want to connect the color of a potion to a type check? Or maybe that's just temporary for ease
* Wouldn't you want to do something with the actual boostevent.getInstigator().exists(); check, and before setting charmov?
* The update loop seems to call itself on the first line within itself. Infinite loop, or a subtly different data type that's actually a different update method?
* Not sure on the exception, you might need you-know-who for that :) Any chance that the event handler is unhappy about its parameters (specific event class type? I can't remember if that's expected without checking the code) and thus doesn't match what's expected by the interface / override properly? I'm probably stabbing in the dark there
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Re: Status Effects [CRASH ISSUE]

Code:
    @ReceiveEvent(components = {SpeedBoostComponent.class})
    public void onActivate(ActivateEvent event, BoostSpeedEvent boostevent, EntityRef entity, SpeedBoostComponent speedEffect) {
should be

Code:
    @ReceiveEvent(components = {SpeedBoostComponent.class})
    public void onActivate(BoostSpeedEvent boostevent, EntityRef entity, SpeedBoostComponent speedEffect) {
It shouldn't crash just because of that, but it won't work. I'll check to see why it is crashing.

Cervator said:
* Wouldn't you want to do something with the actual boostevent.getInstigator().exists(); check, and before setting charmov?
More to the point, you need to actually get the speed effect or create it. You need to stop adding global variables that make your code compile but crash at runtime. :)

* The update loop seems to call itself on the first line within itself. Infinite loop, or a subtly different data type that's actually a different update method?
Yeah, that's an infinite loop.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
I saw another commit hit GitHub - https://github.com/bi0hax/Terasology/co ... 00a75a72a7 - pulled it locally and it didn't seem to crash. Yay?

Was able to get myself a purple potion, which I proceeded to wield like a spear :D

Left click made it go poof, but I didn't feel like I got superpowers or visions or anything. But maybe that's just en route!
 

B!0HAX

Member
Contributor
World
Potions!!

Cervator said:
[...] didn't feel like I got superpowers or visions [...]
The visions are being saved for that red mushroom (looks like an Amanita Muscaria)
But now if you drink a Purple Potion (and hold down shift) you can feel the superpowers! :]

Green Potion doesn't look tasty...
Orange Potion in case you try it.
Red Potion will give you health.

Potion Update
 

overdhose

Active Member
Contributor
Design
World
GUI
purple potions :p sounds yummy
 

begla

Project Founder and Lead Developer
Contributor
Architecture
Logistics
I always liked potions that could kill you if you weren't careful. Okay - I didn't like to drink them... But... The idea of potions with undefined behavior is nice. :twisted:

Last I saw them was in... Dungeons of Dreadmore (I think). But maybe this is a bit too roguelike for our game here? :?:
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
There's always the possibility of a Skyrim-style ingredient-based alchemy system where each ingredient can have multiple effects and you're not sure which they are. Each matching effect between multiple ingredients amplifies that specific effect. So whoops, that steady healing potion you were used to also just gave you fire breath when you added that last tasty-looking morsel...

Anyway, can't wait to merge this in, last thing I'm waiting for before we hit master and 0.4.0 :D
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Integrated! Tested somewhat mixed-bag, the purple potion works great, red throws an exception (but doesn't crash anything) and green/orange I don't see a working effect from - tho I appear to be regenerating, can't remember if that's normal :)

Don't see any status icons either, but none of the issues really impact the game, so pushing it!

For those who haven't tried the purple yet, doooo eeeet!

giveItem "core:purplepotion" + left click to use = weeeeeeeeeeeee (when running, not walking)
 

B!0HAX

Member
Contributor
World
Cervator said:
red throws an exception (but doesn't crash anything) and green/orange I don't see a working effect from - tho I appear to be regenerating, can't remember if that's normal :)

Don't see any status icons either, but none of the issues really impact the game, so pushing it!
*facepalm*
Strange... It worked before I merged, Im going to have a look at it...
Anyways Im going to add the Buff icons, so next update those potions will be working again (and better)...

EDIT: Had a look and It seems that none are actually working properly, the purple is giving the effects but its not giving back the empty vial, so I suppose theres been some change that has affected that Event Handler (DrinkPotionAction).
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Yeah, this is a result of the changes I made to how items are invoked. Previously when you used an item set to usage: OnUser, both the instigator and target of the dispatched ActivateEvent were the Player entity, so you could use either. Because I ripped out the layer that generated different ActivateEvents based on the usage, the ActivateEvent always has whatever the player is looking at (if anything) as the target. So now where biohax was using the ActivateEvent's target, he needs to use the instigator (the user's entity).
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Integrated! Looking good, I even spotted the buff icon now in the upper left, it was previously covered up most the time from having F3 debug info on screen :)

I did get an exception on the new drink sound - dunno if that's just me:

Code:
java.lang.Exception: Input does not appear to be an Ogg bitstream.
	at org.terasology.utilities.OggReader.initVorbis(OggReader.java:280)
	at org.terasology.utilities.OggReader.<init>(OggReader.java:94)
	at org.terasology.asset.loaders.OggSoundLoader.load(OggSoundLoader.java:46)
	at org.terasology.asset.loaders.OggSoundLoader.load(OggSoundLoader.java:40)
	at org.terasology.logic.manager.AssetManager.loadAsset(AssetManager.java:85)
	at org.terasology.logic.manager.AssetManager.load(AssetManager.java:174)
	at org.terasology.logic.manager.AudioManager.getSoundSource(AudioManager.java:83)
	at org.terasology.logic.manager.AudioManager.source(AudioManager.java:130)
	at org.terasology.logic.manager.AudioManager.source(AudioManager.java:163)
	at org.terasology.logic.manager.AudioManager.play(AudioManager.java:227)
	at org.terasology.logic.manager.AudioManager.play(AudioManager.java:215)
	at org.terasology.componentSystem.action.DrinkPotionAction.onActivate(DrinkPotionAction.java:89)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
Not a crash issue, so not a big deal!

Also, I wonder, how hard would it be to make the empty flasks stackable? Would that be the first item needing stackable logic?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Bump! Still out there, B!0HAX ? One of your buff-related commits had been sitting around all lonely for a bit, so to not lose code monkey skills with all this forum tinkering I'm doing these days I went ahead and integrated it to the main develop real quick :)

Saw the stuff come in about the orange cure potion being worked on to also give immunity for a while as well as getting its own icon (and did speed potion always vary its buff icon based on whether or not the player is running? Neat). I understand the immunity doesn't quite work yet (and icon stays up forever), but it sure does cure and the hearts turn color back properly, they didn't last I knew! So progress is progress and now it won't get any dustier :thumbsup:
 
Top