1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "interface_v3/interface_manager.h"
25 #include "forage_source_cl.h"
26 #include "ingame_database_manager.h"
27 #include "debug_client.h"
28 #include "game_share/rm_family.h"
29 #include "client_sheets/forage_source_sheet.h"
30 #include "interface_v3/group_in_scene_user_info.h"
31 #include "fx_manager.h"
32 #include "string_manager_client.h"
33 #include "sheet_manager.h"
36 #include "time_client.h"
37 #include "game_share/constants.h"
38 #include <nel/misc/i18n.h>
41 using namespace NLMISC
;
43 extern class CView View
;
44 extern UCamera MainCam
;
46 const uint8 BarNotInit
= 255;
48 CRGBA
CForageSourceCL::SafeSourceColor(64, 192, 255);
53 CForageSourceCL::CForageSourceCL() :
55 _InSceneUserInterface( NULL
),
56 _IconFilename( NULL
),
57 _IsExtractionInProgress( false ),
60 _LastExplosionSwitch( 0 ),
61 _ProspectorSlot( 255 ),
63 _InclBonusExtraTime(0),
64 _InitialQuantity(BarNotInit
),
67 for ( uint i
=0; i
!=NbFSBarIndices
-1; ++i
)
69 _BarDestValues
[i
] = BarNotInit
;
70 _BarCurrentValues
[i
] = BarNotInit
;
72 _BarDestValues
[NbFSBarIndices
-1] = BarNotInit
;
74 // init to 0 per default (first frames...)
83 * Initialize properties of the entity (according to the class).
85 void CForageSourceCL::initProperties()
87 CFxCL::initProperties();
89 properties().selectable( true );
95 * Build the entity from a sheet.
97 bool CForageSourceCL::build( const CEntitySheet
*sheet
)
101 // Get FX filename and info from the sheet
102 const CForageSourceSheet
*forageSourceSheet
= dynamic_cast<const CForageSourceSheet
*>(sheet
);
103 if ( ! forageSourceSheet
)
105 nlwarning( "Bad sheet %s for forage source", sheet
? sheet
->Id
.toString().c_str() : "NULL" );
108 if ( ! setFx( forageSourceSheet
->FxFilename
) )
110 _KnowledgeLevel
= forageSourceSheet
->Knowledge
;
111 if ( _KnowledgeLevel
!= 0 )
112 _KnowledgeLevel
|= 0x80; // we don't know the group or family yet (visual FX not received)
117 if(IngameDbMngr
.getNodePtr())
119 CCDBNodeBranch
*nodeRoot
= dynamic_cast<CCDBNodeBranch
*>(IngameDbMngr
.getNodePtr()->getNode(0));
122 _DBEntry
= dynamic_cast<CCDBNodeBranch
*>(nodeRoot
->getNode(_Slot
));
124 pushDebugStr("Cannot get a pointer on the DB entry.");
128 // Set default name (with no knowledge)
129 _EntityName
= CI18N::get( "mpSource" );
131 // Build hud interface
132 buildInSceneInterface();
135 UParticleSystemInstance fxInst
;
136 fxInst
.cast (_Instance
);
137 nlassert(!fxInst
.empty());
138 fxInst
.setUserParam( 0, 0.0f
); // inversed opacity
139 fxInst
.setUserParam( 1, 0.0f
); // glow
140 fxInst
.setUserParam( 2, 0.0f
); // particle quantity
147 void CForageSourceCL::resetVP()
150 UParticleSystemInstance fxInst
;
151 fxInst
.cast (_Instance
);
152 nlassert(!fxInst
.empty());
153 fxInst
.setUserParam( 0, 0.0f
); // inversed opacity
154 fxInst
.setUserParam( 1, 0.0f
); // glow
155 fxInst
.setUserParam( 2, 0.0f
); // particle quantity
157 nlinfo( "FG: Source: %s FX: %s", _Position
.asVector().asString().c_str(), fxInst
.getPos().toString().c_str() );
162 * Rebuild in scene interfaces
164 void CForageSourceCL::buildInSceneInterface()
166 // Delete previous interface
167 releaseInSceneInterfaces();
169 _InSceneUserInterface
= CGroupInSceneUserInfo::build( this );
170 _InSceneUserInterface
->setUserScale( true );
173 CFxCL::buildInSceneInterface();
178 * Destroy inscene interfaces
180 void CForageSourceCL::releaseInSceneInterfaces()
182 if (_InSceneUserInterface
)
184 CWidgetManager::getInstance()->unMakeWindow(_InSceneUserInterface
);
185 if (_InSceneUserInterface
->getParent())
187 _InSceneUserInterface
->getParent()->delGroup(_InSceneUserInterface
);
191 delete _InSceneUserInterface
;
194 _InSceneUserInterface
= NULL
;
200 * Called when clipped out
202 void CForageSourceCL::updateClipped (const NLMISC::TTime
¤tTimeInMs
, CEntityCL
*target
)
204 // hide the scene interface
205 if (_InSceneUserInterface
)
207 if (_InSceneUserInterface
->getActive())
208 _InSceneUserInterface
->setActive (false);
212 CFxCL::updateClipped(currentTimeInMs
, target
);
217 * Method called each frame to manage the entity after the clipping test if the primitive is visible.
219 void CForageSourceCL::updateVisible(const NLMISC::TTime
&time
, CEntityCL
*target
)
222 if(!_HPModifiers
.empty())
225 mod
.CHPModifier::operator= (*_HPModifiers
.begin());
226 mod
.Time
= TimeInSec
;
227 _HPDisplayed
.push_back(mod
);
228 _HPModifiers
.erase(_HPModifiers
.begin());
232 CFxCL::updateVisible(time
, target
);
237 * Helper for updateVisualPropertyBars()
239 inline void setBarValue( float& currentValue
, uint8
& displayedValue
, uint8
& newValue
)
241 displayedValue
= newValue
;
242 currentValue
= (float)displayedValue
;
247 * Helper for updateVisiblePostPos()
249 inline void updateBarValueTime( uint8
& destValue
, float& currentValue
, uint8
& displayedValue
)
251 sint8 diff
= (sint8
)(destValue
- displayedValue
);
254 currentValue
= std::max( (float)destValue
, currentValue
- DeltaTimeBarPerSec
*DT
);
255 displayedValue
= (uint8
)currentValue
;
259 currentValue
= (float)destValue
;
260 displayedValue
= destValue
;
266 * Helper for updateVisiblePostPos()
268 inline void updateBarValue( uint8
& destValue
, float& currentValue
, uint8
& displayedValue
)
270 sint8 diff
= (sint8
)(destValue
- displayedValue
);
273 currentValue
= std::max( (float)destValue
, currentValue
- DeltaMoveBarPerSec
*DT
);
274 displayedValue
= (uint8
)currentValue
;
278 float speed
= (destValue
== 127) ? DeltaResetBarPerSec
: DeltaMoveBarPerSec
;
279 currentValue
= std::min( (float)destValue
, currentValue
+ speed
*DT
);
280 displayedValue
= (uint8
)currentValue
;
286 * Update the entity after all positions done.
288 void CForageSourceCL::updateVisiblePostPos(const NLMISC::TTime
&time
, CEntityCL
*target
)
290 // Update in scene interface
291 if( _InSceneUserInterface
)
293 float dist
= (_Position
.asVector() - View
.currentViewPos()/*UserEntity->pos()*/).norm();
295 // Draw the interface is bars received
296 bool showIS
= (dist
< (CLFECOMMON::THRESHOLD_BARS
/1000 - 5.0f
) ); //mustShowInsceneInterface( true );
299 if ( _InSceneUserInterface
->getActive() != showIS
)
300 _InSceneUserInterface
->setActive( showIS
);
305 const float ClampDist
= 8.0f
; // > 0
306 if ( dist
< ClampDist
)
307 _InSceneUserInterface
->Scale
= 1.0f
;
309 _InSceneUserInterface
->Scale
= ClampDist
/ dist
;
311 // Update dynamic data
312 _InSceneUserInterface
->updateDynamicData();
315 NLMISC::CVectorD pos
;
316 pos
= (box().getMin() + box().getMax())/2;
317 pos
.z
= box().getMax().z
; // * 0.7f; // not as high as the top of the box
318 nlassert(isValidDouble(pos
.x
) && isValidDouble(pos
.y
) && isValidDouble(pos
.z
));
319 _InSceneUserInterface
->Position
= pos
;
323 // Update bar delayed movement
324 updateBarValueTime( _BarDestValues
[FSBTime
], _BarCurrentValues
[FSBTime
], _TimeBar
); // Time (slower transition)
325 updateBarValue( _BarDestValues
[FSBQuantiy
], _BarCurrentValues
[FSBQuantiy
], _QuantityBar
); // Qtty
326 updateBarValue( _BarDestValues
[FSBD
], _BarCurrentValues
[FSBD
], _DBar
); // D
327 updateBarValue( _BarDestValues
[FSBE
], _BarCurrentValues
[FSBE
], _EBar
); // E
330 CFxCL::updateVisiblePostPos(time
, target
);
334 void CForageSourceCL::displayInscenePos()
336 nlinfo( "FG: Source: %s Inscene: %s % slot: %u", _Position
.asVector().asString().c_str(), _InSceneUserInterface
->Position
.asString().c_str(), (slot() == UserEntity
->selection()) ? "SELECTED":"Unselected", slot() );
341 * Update Entity Visual Property B
343 /*void CForageSourceCL::updateVisualPropertyVpb(const NLMISC::TGameCycle &gameCycle, const sint64 &prop)
349 bool ForageSourceUseUP
;
350 float ForageSourceUP0
;
351 float ForageSourceUP1
;
352 float ForageSourceUP2
;
353 float ForageSourceUP3
;
354 NLMISC_VARIABLE( bool, ForageSourceUseUP
, "Use debug user param" );
355 NLMISC_VARIABLE( float, ForageSourceUP0
, "" );
356 NLMISC_VARIABLE( float, ForageSourceUP1
, "" );
357 NLMISC_VARIABLE( float, ForageSourceUP2
, "" );
358 NLMISC_VARIABLE( float, ForageSourceUP3
, "" );
364 void CForageSourceCL::updateVisualPropertyBars(const NLMISC::TGameCycle
&/* gameCycle */, const sint64
&prop
)
366 // NB: forage don't use CBarManager for 2 reasons: useless (forage bars exist only through VP),
367 // and complicated since updated at each frame on client (because of smooth transition code below)
369 bool setBarsNow
= (_BarDestValues
[0] == BarNotInit
);
370 _BarDestValues
[FSBTime
] = (uint8
)(prop
&0x7f); // Time to live
371 _BarDestValues
[FSBD
] = (uint8
)((prop
>>14)&0x7f); // D
372 _BarDestValues
[FSBE
] = (uint8
)((prop
>>21)&0x7f); // E
373 // Deal with safe sources
374 if (_BarDestValues
[FSBE
]==0) // Safe source
376 _BarDestValues
[FSBE
] = 127;
377 /* // This is disabled coz setFx don't work after entity creation (:TODO: try to see why)
380 CEntitySheet *entitySheet = SheetMngr.get(sheetId());
381 const CForageSourceSheet *forageSourceSheet = dynamic_cast<const CForageSourceSheet*>(entitySheet);
382 if ( forageSourceSheet )
384 if ( ! setFx( forageSourceSheet->FxSafeFilename ) )
385 setFx( forageSourceSheet->FxFilename );
393 /* // This is disabled coz setFx don't work after entity creation (:TODO: try to see why)
396 CEntitySheet *entitySheet = SheetMngr.get(sheetId());
397 const CForageSourceSheet *forageSourceSheet = dynamic_cast<const CForageSourceSheet*>(entitySheet);
398 if ( forageSourceSheet )
399 setFx( forageSourceSheet->FxFilename );
406 setBarValue( _BarCurrentValues
[FSBTime
], _TimeBar
, _BarDestValues
[FSBTime
] );
407 _InitialQuantity
= ((uint8
)((prop
>>7)&0x7f)); // Quantity
408 if ( _InitialQuantity
!= 0 )
410 _CurrentQuantity
= _InitialQuantity
;
411 _BarDestValues
[FSBQuantiy
] = 127;
415 _CurrentQuantity
= 0;
416 _BarDestValues
[FSBQuantiy
] = 0;
418 setBarValue( _BarCurrentValues
[FSBQuantiy
], _QuantityBar
, _BarDestValues
[FSBQuantiy
] );
419 setBarValue( _BarCurrentValues
[FSBD
], _DBar
, _BarDestValues
[FSBD
] );
420 setBarValue( _BarCurrentValues
[FSBE
], _EBar
, _BarDestValues
[FSBE
] );
424 _CurrentQuantity
= (uint8
)((prop
>>7)&0x7f);
425 _BarDestValues
[1] = (_InitialQuantity
!= 0) ? (_CurrentQuantity
* 127 / _InitialQuantity
) : 0; // Quantity
428 if ( ! _IsExtractionInProgress
)
430 _IsExtractionInProgress
= (bool)((prop
>>28)&1);
431 if ( _IsExtractionInProgress
)
432 buildInSceneInterface(); // Rebuild hud interface
435 if ( !_Instance
.empty() )
437 UParticleSystemInstance fxInst
;
438 fxInst
.cast (_Instance
);
439 nlassert(!fxInst
.empty());
440 if ( ForageSourceUseUP
)
442 fxInst
.setUserParam( 0, ForageSourceUP0
);
443 fxInst
.setUserParam( 1, ForageSourceUP1
);
444 fxInst
.setUserParam( 2, ForageSourceUP2
);
445 fxInst
.setUserParam( 3, ForageSourceUP3
);
449 // Link Time to live to user param 1 (127-> 0=bright; 0-> 0.9=dark&transparent)
450 fxInst
.setUserParam( 0, 1.0f
- (((float)_BarDestValues
[0])*(0.9f
/ 127.0f
) + 0.1f
) );
452 // Link E to user param 1 (glow)
453 fxInst
.setUserParam( 1, ((float)(127-_BarDestValues
[3])) / 127.0f
);
454 // :TODO: Find a way to change fx or fx color. setUserColor does a modulate, so it's not suitable.
456 // fxInst.setUserColor(CRGBA(255,0,0));
458 // Link Quantity to user param 2 (particle quantity)
459 fxInst
.setUserParam( 2, std::min( 1.0f
, ((float)_CurrentQuantity
) / 50.0f
) ); // map 100% to quantity 50
466 * Update Entity Orientation.
467 * Used to carry the kami anger bar (does not change often)
469 void CForageSourceCL::updateVisualPropertyOrient(const NLMISC::TGameCycle
&/* gameCycle */, const sint64
&prop
)
472 _BarDestValues
[4] = (uint8
)(u
&0x7f);
473 _ExtraTime
= (uint8
)((u
>>7)&0x7f);
474 _InclBonusExtraTime
= (uint8
)((u
>>14)&0x7f);
480 * Contains group or family (if knowledge is 1 or 2-3), and explosion state.
482 void CForageSourceCL::updateVisualPropertyVisualFX(const NLMISC::TGameCycle
&/* gameCycle */, const sint64
&prop
)
484 // Display explosion FX if the switch flag tells us to do it
485 uint8 receivedExplosionSwitch
= (uint8
)((prop
& 0x400) >> 10);
486 if ( receivedExplosionSwitch
&& (receivedExplosionSwitch
!= _LastExplosionSwitch
) ) // bit 10
488 UParticleSystemInstance fxNewInst
= FXMngr
.instantFX( "FOR_explosion.ps" );
489 if ( !fxNewInst
.empty() )
490 fxNewInst
.setPos( pos() );
492 _LastExplosionSwitch
= receivedExplosionSwitch
;
494 // Set family or group knowledge info
495 if ( (_KnowledgeLevel
& 0x80) != 0 )
497 uint32 index
= (uint32
)(prop
&0x3ff); // 10 bits
498 _KnowledgeLevel
&= 0x7F;
499 switch ( _KnowledgeLevel
)
501 //case 0: default name unchanged
502 case 1: _EntityName
= RM_GROUP::toLocalString( (RM_GROUP::TRMGroup
)index
); break; // display group as title
503 case 2: _EntityName
= RM_FAMILY::toLocalString( (RM_FAMILY::TRMFamily
)index
); break; // display family as title
504 // case 3: received by property Name (see below)
506 if ( (_KnowledgeLevel
<=2) && (_ProspectorSlot
!= 255) )
508 CEntityCL
*prospector
= EntitiesMngr
.entities()[_ProspectorSlot
];
509 if (prospector
!= NULL
)
511 string prospectorName
= prospector
->getDisplayName();
512 if ( ! prospectorName
.empty() )
513 _EntityName
+= " [" + prospectorName
+ "]";
517 // Set icon (2 and 3: the family index is transmitted (for knowledge 3, used only as icon index))
518 CEntitySheet
*sheet
= SheetMngr
.get( sheetId() );
519 const CForageSourceSheet
*forageSourceSheet
= dynamic_cast<const CForageSourceSheet
*>(sheet
);
520 if ( forageSourceSheet
&& (index
< forageSourceSheet
->Icons
.size()) )
522 _IconFilename
= &(forageSourceSheet
->Icons
[index
]);
525 // Rebuild inscene interface
526 buildInSceneInterface();
532 * Update Entity Name.
533 * Interpret the property Name as the sheet id (it's not the usual string id!) of
534 * the raw material, when the knowledge is 3.
536 void CForageSourceCL::updateVisualPropertyName(const NLMISC::TGameCycle
&/* gameCycle */, const sint64
&prop
)
538 CSheetId
rmSheetId( (const uint32
&)prop
);
539 const char *name
= STRING_MANAGER::CStringManagerClient::getItemLocalizedName( rmSheetId
);
543 if ( _ProspectorSlot
!= 255 )
545 CEntityCL
*prospector
= EntitiesMngr
.entities()[_ProspectorSlot
];
546 if (prospector
!= NULL
)
548 std::string prospectorName
= prospector
->getDisplayName();
549 if ( ! prospectorName
.empty() )
550 _EntityName
+= " [" + prospectorName
+ "]";
553 // Rebuild inscene interface
554 buildInSceneInterface();
560 * Update Entity Target.
562 void CForageSourceCL::updateVisualPropertyTarget(const NLMISC::TGameCycle
&/* gameCycle */, const sint64
&prop
)
564 sint slot
= (sint
)prop
;
565 if ( slot
!= CLFECOMMON::INVALID_SLOT
)
567 _ProspectorSlot
= slot
;
568 CEntityCL
*prospector
= EntitiesMngr
.entities()[_ProspectorSlot
]; // NULL if entity not received
569 if (prospector
!= NULL
)
571 std::string prospectorName
= prospector
->getDisplayName();
572 if ( ! prospectorName
.empty() )
573 _EntityName
= _EntityName
+ " [" + prospectorName
+ "]";
576 // Rebuild inscene interface
577 buildInSceneInterface();
583 * Display the modifiers
585 void CForageSourceCL::displayModifiers()
588 if( _HPDisplayed
.empty())
591 // **** get the name pos
592 NLMISC::CVector namePos
= pos() + CVector(0.f
, 0.f
, 0.8f
);
594 // **** compute the scale
595 float dist
= (MainCam
.getPos()-pos()).norm();
597 if(dist
> ClientCfg
.MaxNameDist
)
599 if ( dist
< ClientCfg
.ConstNameSizeDist
)
602 scale
= ClientCfg
.ConstNameSizeDist
/ dist
;
605 // **** Display HP modifiers.
606 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
607 std::list
<HPMD
>::iterator itTmp
;
608 std::list
<HPMD
>::iterator it
= _HPDisplayed
.begin();
609 while(it
!= _HPDisplayed
.end())
613 const float totalDuration
= 3.f
;
614 const float noFadeDuration
= 1.f
;
615 const float fadeDuration
= totalDuration
-noFadeDuration
;
616 if(TimeInSec
> (mod
.Time
+totalDuration
))
620 _HPDisplayed
.erase(itTmp
);
624 uint16 qttyDelta
= ((uint16
)mod
.Value
) & 0xFF;
625 uint16 qlty
= ((uint16
)mod
.Value
) >> 8;
626 string hpModifier
= toString("%u ", qttyDelta
) + CI18N::get("uittQualityAbbrev") + toString(" %u", qlty
);
627 double t
= TimeInSec
-mod
.Time
;
628 // Compute the position for the Modifier.
629 CVector pos
= namePos
+ CVector(0.0f
, 0.0f
, 0.3f
+(float)t
*1.0f
/totalDuration
);
633 color
= CRGBA(220,0,0);
635 color
= CRGBA(0,220,0);
640 color
.A
= 255-(uint8
)((t
-noFadeDuration
)*255.0/fadeDuration
);
643 pIM
->FlyingTextManager
.addFlyingText(&mod
, hpModifier
, pos
, color
, scale
);
655 CForageSourceCL::~CForageSourceCL()
657 releaseInSceneInterfaces();
661 /*NLMISC_COMMAND( resetSourceVP, "", "" )
663 CLFECOMMON::TCLEntityId slot = UserEntity->selection();
664 CEntityCL *selection = EntitiesMngr.entities()[slot];
665 if ( selection && selection->isForageSource() )
667 ((CForageSourceCL*)selection)->resetVP();
672 CForageSourceCL *ViewedSource = NULL;
674 NLMISC_COMMAND( viewSourcePos, "", "" )
676 CLFECOMMON::TCLEntityId slot = UserEntity->selection();
677 CEntityCL *selection = EntitiesMngr.entities()[slot];
678 if ( selection && selection->isForageSource() )
680 ViewedSource = ((CForageSourceCL*)selection);
681 ViewedSource->displayInscenePos();
686 ViewedSource->displayInscenePos();