Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / forage_source_cl.cpp
blob7141ad62f26026996e21faa00ead10c75b0ee24b
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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>
7 //
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/>.
23 #include "stdpch.h"
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"
34 #include "entities.h"
35 #include "view.h"
36 #include "time_client.h"
37 #include "game_share/constants.h"
38 #include <nel/misc/i18n.h>
40 using namespace NL3D;
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);
51 * Constructor
53 CForageSourceCL::CForageSourceCL() :
54 CFxCL(),
55 _InSceneUserInterface( NULL ),
56 _IconFilename( NULL ),
57 _IsExtractionInProgress( false ),
58 _SafeSource( false ),
59 _KnowledgeLevel( 0 ),
60 _LastExplosionSwitch( 0 ),
61 _ProspectorSlot( 255 ),
62 _ExtraTime(0),
63 _InclBonusExtraTime(0),
64 _InitialQuantity(BarNotInit),
65 _CurrentQuantity(0)
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...)
75 _TimeBar= 0;
76 _QuantityBar= 0;
77 _DBar= 0;
78 _EBar= 0;
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 )
99 //_CrtCheckMemory();
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" );
106 return false;
108 if ( ! setFx( forageSourceSheet->FxFilename ) )
109 return false;
110 _KnowledgeLevel = forageSourceSheet->Knowledge;
111 if ( _KnowledgeLevel != 0 )
112 _KnowledgeLevel |= 0x80; // we don't know the group or family yet (visual FX not received)
114 // Base class init
115 initialize();
116 Type = ForageSource;
117 if(IngameDbMngr.getNodePtr())
119 CCDBNodeBranch *nodeRoot = dynamic_cast<CCDBNodeBranch *>(IngameDbMngr.getNodePtr()->getNode(0));
120 if(nodeRoot)
122 _DBEntry = dynamic_cast<CCDBNodeBranch *>(nodeRoot->getNode(_Slot));
123 if(_DBEntry == 0)
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();
134 // Init user params
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
142 //_CrtCheckMemory();
143 return true;
147 void CForageSourceCL::resetVP()
149 // Init user params
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 );
172 // parent
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);
189 else
191 delete _InSceneUserInterface;
194 _InSceneUserInterface = NULL;
200 * Called when clipped out
202 void CForageSourceCL::updateClipped (const NLMISC::TTime &currentTimeInMs, CEntityCL *target)
204 // hide the scene interface
205 if (_InSceneUserInterface)
207 if (_InSceneUserInterface->getActive())
208 _InSceneUserInterface->setActive (false);
211 // parent
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)
221 // Update Modifiers
222 if(!_HPModifiers.empty())
224 HPMD mod;
225 mod.CHPModifier::operator= (*_HPModifiers.begin());
226 mod.Time = TimeInSec;
227 _HPDisplayed.push_back(mod);
228 _HPModifiers.erase(_HPModifiers.begin());
231 // parent
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);
252 if ( diff < 0 )
254 currentValue = std::max( (float)destValue, currentValue - DeltaTimeBarPerSec*DT );
255 displayedValue = (uint8)currentValue;
257 else if ( diff > 0 )
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);
271 if ( diff < 0 )
273 currentValue = std::max( (float)destValue, currentValue - DeltaMoveBarPerSec*DT );
274 displayedValue = (uint8)currentValue;
276 else if ( diff > 0 )
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 );
298 // Activate
299 if ( _InSceneUserInterface->getActive() != showIS )
300 _InSceneUserInterface->setActive( showIS );
302 if ( showIS )
304 // Scale it
305 const float ClampDist = 8.0f; // > 0
306 if ( dist < ClampDist )
307 _InSceneUserInterface->Scale = 1.0f;
308 else
309 _InSceneUserInterface->Scale = ClampDist / dist;
311 // Update dynamic data
312 _InSceneUserInterface->updateDynamicData();
314 // Update position
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
329 // Parent
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, "" );
362 * Update Entity Bars
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)
378 if (!_SafeSource)
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 );
389 _SafeSource = true;
391 else
393 /* // This is disabled coz setFx don't work after entity creation (:TODO: try to see why)
394 if (_SafeSource)
396 CEntitySheet *entitySheet = SheetMngr.get(sheetId());
397 const CForageSourceSheet *forageSourceSheet = dynamic_cast<const CForageSourceSheet*>(entitySheet);
398 if ( forageSourceSheet )
399 setFx( forageSourceSheet->FxFilename );
402 _SafeSource = false;
404 if ( setBarsNow )
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;
413 else
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] );
422 else
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 );
447 else
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.
455 // if (_SafeSource)
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)
471 uint u = (uint)prop;
472 _BarDestValues[4] = (uint8)(u&0x7f);
473 _ExtraTime = (uint8)((u>>7)&0x7f);
474 _InclBonusExtraTime = (uint8)((u>>14)&0x7f);
479 * Update Visual FX.
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 );
540 if ( name )
542 _EntityName = name;
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()
587 // if none, no op
588 if( _HPDisplayed.empty())
589 return;
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();
596 float scale= 1.f;
597 if(dist > ClientCfg.MaxNameDist)
598 return;
599 if ( dist < ClientCfg.ConstNameSizeDist )
600 scale = 1.0f;
601 else
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())
611 HPMD &mod = *it;
613 const float totalDuration= 3.f;
614 const float noFadeDuration= 1.f;
615 const float fadeDuration= totalDuration-noFadeDuration;
616 if(TimeInSec > (mod.Time+totalDuration))
618 itTmp = it;
619 ++it;
620 _HPDisplayed.erase(itTmp);
622 else
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);
630 // get the color
631 CRGBA color;
632 if(mod.Value < 0)
633 color = CRGBA(220,0,0);
634 else
635 color = CRGBA(0,220,0);
636 // fade
637 if(t<noFadeDuration)
638 color.A= 255;
639 else
640 color.A= 255-(uint8)((t-noFadeDuration)*255.0/fadeDuration);
642 // Display the name
643 pIM->FlyingTextManager.addFlyingText(&mod, hpModifier, pos, color, scale);
645 // Next
646 ++it;
653 * Destructor
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();
669 return true;
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();
683 else
685 // Use with caution
686 ViewedSource->displayInscenePos();
688 return true;